n 개의 이상한 숫자 인쇄


12

기수는 적절한 제수의 합이 숫자 자체보다 크며 적절한 제수의 부분 집합이 해당 숫자에 합치 지 않는 숫자입니다.

예 :

70은 적절한 제수 (1, 2, 5, 7, 10, 14, 35)가 74보다 큰 74이고,이 수의 조합은 70이 아니기 때문에 이상한 수입니다.

18은 적절한 제수 (1, 2, 3, 4, 6, 9)의 합이 25보다 크지 만 18보다 크지 만 3, 6, 9의 합은 18이기 때문에 이상한 수는 아닙니다.

당신의 임무는 숫자 n 을 std-in을 통해 입력 하고 파일로 계산하고 인쇄하거나 줄 바꿈으로 첫 n 개의 이상한 숫자를 std-out하는 가장 짧은 프로그램을 작성하는 것입니다. 답변의 하드 코딩은 허용되지 않습니다 (처음에는 이것을 지정하지 않아서 죄송합니다).

더 많은 예를 보려면 다음 페이지를 참조하십시오 : http://mathworld.wolfram.com/WeirdNumber.html


1
이 질문이 샌드 박스에있을 때는 "calculate"라는 단어에 이미 "하드 코딩 없음"규칙을 추가해야한다고 언급하지 않았습니다. 나는 사람들이 결과를 계산하지 않는 모든 답변을 답답하지 않거나 저품질로 표시하도록 권장합니다. ( 관련 메타 토론 ).
피터 테일러

답변:


2

매스 매 티카 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


4

하스켈-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 '

2

파이썬 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";
}

무차별 대입 검증을 수행 할 때 숫자를 출력하는 데 시간이 걸린다는 점에 유의해야합니다.


1

제 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가 포함 된 루비-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논리 값에 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

이것은 하위 집합의 합계를 계산하는 데 도움을 요청하기 위해 내 솔루션이 아닌 모든 것이 내 것입니다.

#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) 만 계산했습니다. 그 후 나는 그것을 죽였다.


읽기 쉬운 버전도 게시하는 것이 좋을 것입니다. 특히 하나의 라이너로 만들었 기 때문에;)
yo '

@tohecz 물론 편집하겠습니다.

@tohecz 끝났어요.

1

펄, 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+$))+숫자의 요인과 일치합니다. 이후 반복은 이전 반복보다 작은 요소와 일치합니다.

  • 우리는이 두 부분 (.+)(?=.*(?=\1$)\3+$)함께 검사중인 숫자의 요소를 선택 한다는 것을 알 수 있습니다 .
  • (?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$)) 선택한 요인이 첫 번째 반복에서 확인중인 숫자보다 작고 후속 반복에서 이전 요인보다 작습니다.

정규식은 2의 한계 내에서 가능한 많은 수의 요소를 일치 시키려고합니다 i. 그러나 우리는 제수의 합의 실제 가치에 관심이 없으며 숫자가 풍부한 지 여부에만 관심이 있습니다.

그런 다음 두 번째 정규 표현식이 \1{2}$추가 된 첫 번째 정규 표현식입니다 . 결과적으로, 정규 표현식은 확인되는 숫자의 (일부) 요인의 합이 숫자 자체와 같은지 확인합니다.

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

제약 조건이 추가되면 정규식 엔진이 모든 가능한 요소 하위 집합에 대해 역 추적 검색을 수행하므로 속도가 매우 느려집니다.


1

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.