最短的素数计算代码

3

我在学校计算机科学专业的报纸(叫做readme,挪威语,第19页)上看到了一个有趣的比赛,要求编写最短的Java代码来解决以下问题。

输入一个整数(作为字符串数组的第一个输入参数,因为Java主方法只接受字符串数组),首先输出所有小于此数字的质数,然后输出所有非质数。最短的代码获胜!

我将发布获胜比赛的最短Java代码。我想知道Stack Overflow社区是否能编写出更短的代码。如果你懂挪威语,你会发现如果你做到了,你可以赢得一瓶香槟,但不幸的是比赛的最后提交日期已经过去了。

你会如何解决这个问题?


用什么语言?Java并不是以简洁著称的语言。 - Unknown
我同意。已编辑并将其设为社区维基。 :) - Espen Herseth Halvorsen
添加了一些澄清.. :) - Espen Herseth Halvorsen
我移除了对Java的要求。 - Espen Herseth Halvorsen
您可能希望将其标记为“language-agnostic”和“rosetta-stone”。 - Brad Gilbert
显示剩余2条评论
9个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
6

在您将标题更改为“Java”之前,我已经在Haskell中进行了这项工作。由于这是一个社区维基,所以我还是将其提供给大家。

primes n = 
let sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0] in 
let primes = takeWhile (<n) $ sieve [2..] in 
([0..n] \\ primes, primes)

*Main> primes 20
([0,1,4,6,8,9,10,12,14,15,16,18,20],[2,3,5,7,11,13,17,19])

(编辑:)缩短名称并删除空格可使其为79个字符:

p n=let s(p:xs)=p:s[x|x<-xs,x`mod`p/=0];r=takeWhile(<n)$s[2..]in(r,[0..n-1]\\r)

在这里,产生的一对也会交换顺序,并按规范使用n-1

使用次优的试除法将其降至50个字符

p n=partition(\k->all((>0).rem k)[2..k-1])[2..n-1]

不错。这可以通过使用简单的试除法来缩短,而不是使用筛法(上述算法的性能比试除法差;请参阅Melissa O'Neill的论文)。 - Gracenotes
@Gracenotes,你有这篇论文的链接吗? - Unknown
1
如果有人提出更短的答案,我会更改接受状态。请接受此答案。 - Espen Herseth Halvorsen
1
我认为Gracenotes指的是这篇论文:The Genuine Sieve of Eratosthenes - user49117

4
该比赛获胜的Java代码(不包含空格153个字节,为了易读性包括空格在内):
class F {
   public static void main(String[] a) {
      for (int i, j, k = 2; k-- > 0;)
         for (i = 1; i++ < new Long(a[0]);) {
            for (j = i; i % --j > 0;)
               ;
            if (k > 0 ? j < 2 : j > 1)
               System.out.println(i);
         }
      }
   }

1
此程序对于大于 Integer.MAX_VALUE 的输入不会终止。 - Apocalisp
new Long(String)相对于Long.parseLong(String)在循环中较为昂贵,但它更短。 ;) - Peter Lawrey

3

仅供娱乐,这里有一个Java版本的之前的Haskell答案。只要堆足够大,该程序就能对所有参数进行终止。

import fj.data.Natural;
import fj.data.Stream;
import static fj.data.Stream.*;
import static fj.pre.Ord.naturalOrd;
import fj.pre.Show;
import static fj.pre.Show.streamShow;
import static fj.pre.Show.naturalShow;
import static fj.data.Natural.ZERO;
import static fj.data.Natural.natural;
import fj.P1;
import fj.F;
import static fj.data.Enumerator.naturalEnumerator;

import java.math.BigInteger;

public class Primes2
  {public static Stream<Natural> sieve(final Stream<Natural> xs)
    {return cons(xs.head(), new P1<Stream<Natural>>()
      {public Stream<Natural> _1()
        {return sieve(xs.tail()._1().filter(new F<Natural, Boolean>()
          {public Boolean f(final Natural x)
            {return !naturalOrd.eq(x.mod(xs.head()), ZERO);}}));}});}

  public static Stream<Natural> primes(final Natural n)
    {return sieve(forever(naturalEnumerator, natural(2).some()))
            .takeWhile(naturalOrd.isLessThan(n));}

  public static void main(final String[] a)
    {final Natural n = natural(new BigInteger(a[0])).some();
     final Show<Stream<Natural>> s = streamShow(naturalShow);
     s.println(primes(n));
     s.println(range(naturalEnumerator, ZERO, n)
               .minus(naturalOrd.equal(), primes(n)));}
}

The fj package is from here.


1
如果您需要一段JS代码:n是最大值(62个字符)。
  for(i=1; i<n;i++)
    {
        for(f = j= 2;j<i && f;)
            f = i%j++
        if(f) console.log(i)
    }

1

Python,65个字符

print[i for i in range(2,input())if all(i%j for j in range(2,i))]

使用方法:

>>> print[i for i in range(2,input())if all(i%j for j in range(2,i))]
70
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67]
>>> 

1

我的Ruby尝试。93个字符。

def s n
(a=(2..n).to_a).each{|n|a.reject!{|k|k%n==0&&k/n!=1}}
p[[1]+a,(2..n).to_a-a]
end

0
一个易于理解且智能的代码可能是这样的:
public class test3 {
    public static void main(String[] args) {
        for (int i = 2; i <= 100; i++) {
            int count = 0;
            for (int j = i / 2; j >= 2; j--) {
                if (i % j == 0)
                    count = count + 1;
            }
            if (count == 0)
                System.out.println(i);
        }
    }
}

0
为了完整性,还有两个Haskell定义。原型。
primes = map head . scanl (\\) [2..] . map (\p -> [p, p+p..]) $ primes
         where
         (\\) = Data.List.Ordered.minus

并且在简洁性方面绝对是冠军,

nubBy (((>1).).gcd) [2..]           -- (((>1).).gcd) meaning (\a b -> gcd a b > 1)

-2

133个字符 :-)

class F {

    public static void main(String[] z) {

        l:
        for (int a=1,b; a < z; a += 2) {

            for (b = 2; b < a; b++)
                if (a % b == 0) 
                    continue l;
            System.out.println(a);
        }
    }
}

1
将1列为质数,不将2列为质数,不列出非质数,并且在使用jre-1.7进行测试时需要修改才能运行。 - cjc343

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,