Code Golf:Happy Primes!

mjs*_*ltz 49 language-agnostic code-golf rosetta-stone

这是周日,一轮代码高尔夫的时间!

挑战

通过字符计数写出最短的源代码,以确定输入数字是"幸福素数","悲伤素数","快乐非素数"还是"悲伤非素数".

输入

输入应该是来自命令行参数或stdin的整数.不要担心处理大数字,但如果可以/想要这样做.对于小于1的输入值,行为将是未定义的,但是1具有明确的结果.

产量

输出应该打印数字的类型:"快乐素数","悲伤素数","快乐非素数"或"悲伤的非素数".尾随换行符是可选的.

例子

$ happyprime 139
happy prime
$ happyprime 2
sad prime
$ happyprime 440
happy non-prime
$ happyprime 78
sad non-prime
Run Code Online (Sandbox Code Playgroud)

定义

以防你的大脑需要复习.

快乐的号码

来自维基百科,

快乐数由下面的过程来定义.从任何正整数开始,将数字替换为其数字的平方和,并重复该过程,直到数字等于1(它将保持不变),或者在一个不包括1的循环中无休止地循环.这些数字这个过程在1结束的是快乐的数字,而那些不以1结尾的是不愉快的数字(或悲伤的数字).

例如,

  • 139
  • 1 ^ 2 + 3 ^ 2 + 9 ^ 2 = 91
  • 9 ^ 2 + 1 ^ 2 = 82
  • 8 ^ 2 + 2 ^ 2 = 68
  • 6 ^ 2 + 8 ^ 2 = 100
  • 1 ^ 2 + 0 ^ 2 + 0 ^ 2 = 1

素数

一个素数是大于1的整数且具有恰好两个除数:1和它本身.

快乐总理

因此,幸福的素数是一个快乐和素数的数字.

答案选择

显然,答案将是按字符数排序的最短源代码,在我测试的所有情况下输出指定的结果.一旦下一个(社区决定)代码高尔夫挑战出现,我将标记答案,因此我们可以将所有精力集中在那个.:)

决策

好吧,看起来镇上有一个新的代码高尔夫,自问题发布以来已经有一周了,所以我将最短的源代码标记为答案(gnibbler的64个字符的Golfscript解决方案).也就是说,我很喜欢belisarius 的99字符Mathematica解决方案和Nabb的神秘107字符直流解决方案.

对所有其他人来说,工作很棒!我的计算机上从未有过如此多的编程语言环境.我希望每个人都为自己喜欢的语言学习一些新的,肮脏的技巧.

重用

我已经重新发布了本次竞赛产生的一些代码,作为我编写的脚本示例,用于针对自动分级的参考实现测试各种程序.该目录中的README解释了源代码的来源,并声明所有代码都在CC BY-SA 2.5许可下重新使用(如SO的法律部分所述).每个目录在提交时都标有您的显示名称.

如果您的代码以这种方式重新使用或归属有问题,请告诉我,我将更正错误.

Nab*_*abb 67

dc - 98个字符

$ cat happyprimes
[happy][sad]?dsI[[I~d*rd0<H+]dsHxd4<h]dshx[r]sr1=rP[ ][ non-]_1lI[1-d2>rdlIr%0<p]dspx-2=rP[prime]p
$ echo 1  |dc happyprimes
happy non-prime
$ echo 139|dc happyprimes
happy prime
$ echo 2  |dc happyprimes
sad prime
$ echo 440|dc happyprimes
happy non-prime
$ echo 78 |dc happyprimes
sad non-prime
Run Code Online (Sandbox Code Playgroud)

  • 这个星球来自哪个星球? (32认同)
  • 地狱?(15个字符) (9认同)
  • 关于`dc`:[Wikipedia](http://en.wikipedia.org/wiki/Dc_%28computer_program%29),[manpage](http://linux.die.net/man/1/dc). (2认同)

Dr.*_*ius 29

Mathematica 115 108 107 102 100 99 91 87 Chars


87个字符

Print[If[Nest[Tr[IntegerDigits@#^2]&,#,9]>1,Sad,Happy],If[PrimeQ@#," "," non-"],prime]&
Run Code Online (Sandbox Code Playgroud)

- 瓦格先生


达猴学会了一些技巧(91个字符)

 Print[
       If[Nest[Plus@@(IntegerDigits@ #^2) &, #, 9] > 1, Sad, Happy ],
       If[PrimeQ@#, " ", " non-"], prime
      ] &
Run Code Online (Sandbox Code Playgroud)

调用%[7]

编辑5 - 99个字符/

九次迭代就足够了.谢谢@Nabb,@ mjschultz

h = Print[
    If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 9] > 1, "Sad ", "Happy "]
   , If[PrimeQ@#, "", "non-"], "prime"] &
Run Code Online (Sandbox Code Playgroud)

编辑4 - 100个字符/

与编辑3相同,将10 ^ 2替换为99(允许输入值为84位)...谢谢,@ Greg

h = Print[
    If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 99] > 1, "Sad ", "Happy "]
   , If[PrimeQ@#, "", "non-"], "prime"] &
Run Code Online (Sandbox Code Playgroud)

编辑3 - 102个字符/

再次重写循环.

有趣的是,直到最终达到1的递归深度受到(15 +参数的位数)的限制.看到这里

因此对于少于85位的数字(我认为这个限制非常适合OP的"不要担心处理大数字"的考虑)以下代码可行

h = Print[
    If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 10^2] > 1, "Sad ", "Happy "]
   , If[PrimeQ@#, "", "non-"], "prime"] &
Run Code Online (Sandbox Code Playgroud)

我为较短的"Nest"更改了"NestWhile",因此,不是为递归指定停止条件,而是足以硬编码所需的递归深度(10 ^ 2).

这不是很有效,但这是高尔夫球手的生活:D

编辑2 - 107个字符/

重写了悲伤/快乐的任务

h = Print[
     If[NestWhile[Plus @@ (IntegerDigits@#^2) &, #, # > 4 &] > 1,"Sad ","Happy "]
    ,If[PrimeQ@#, "", "non-"]
    , "prime"] &
Run Code Online (Sandbox Code Playgroud)

除文字外的所有空格/换行都是可选的,并且为了便于阅读而添加

说明:

    NestWhile[Plus @@ (IntegerDigits@#^2) &, #, # > 4 &]
Run Code Online (Sandbox Code Playgroud)

递归应用"函数"[加上平方数加总和]直到结果为4或更小.该函数具有停滞在"1"或进入循环{4,16,37,58,89,145,42,20,4,...}的特性.

因此,当结果为"1"时,数字为"快乐",当结果为"4"时,结果为"悲伤".

如果结果为"2",则该数字也是SAD,因为它将在下一次迭代中进入SAD循环(2 ^ 2 = 4).

如果结果为3,则循环为3-> 9-> 81-> 65-> 61-> 37-> 58-> 89-> 145-> ....(进入SAD循环).

因此,当结果为4或更小时,我们可以停止递归,知道只有"1"的结果将导致Happy数字.

也许其他解决方案可以利用这一事实.

事实上,结果5和6也导致SAD数字,但这只会提高效率而不是高尔夫优势(我猜).

编辑1 - 108个字符/

重写了循环控制逻辑

    h = Print[
        NestWhile[Plus@@(IntegerDigits@#^2) &, #, #>4 &] /.{1 ?"Happy ",_?"Sad "}
          , If[PrimeQ@#, "", "non-"]
          , "prime"] &
Run Code Online (Sandbox Code Playgroud)

原创 - 115 Chars /

h = Print[
    If[NestWhile[Plus @@ (IntegerDigits@#^2) &, #, Unequal, All] == 1
        ,"Happy ", "Sad "],      
    If[PrimeQ@#, "", "non-"], "prime"] &
Run Code Online (Sandbox Code Playgroud)

该声明

NestWhile[Plus @@ (IntegerDigits@#^2) &, #, Unequal, All]
Run Code Online (Sandbox Code Playgroud)

执行递归应用平方数字的总和,直到某些值重复."Unequal,All"部分负责比较前面的值列表.最后返回重复值,对于Happy Numbers为"1".

样品运行

h[7]
Happy prime
h[2535301200456458802993406410753]
Sad non-prime
Run Code Online (Sandbox Code Playgroud)

循环(略微更改Print语句)

1 Happy non-prime
2 Sad prime
3 Sad prime
4 Sad non-prime
5 Sad prime
6 Sad non-prime
7 Happy prime
8 Sad non-prime
9 Sad non-prime
10 Happy non-prime
11 Sad prime
12 Sad non-prime
13 Happy prime
Run Code Online (Sandbox Code Playgroud)

  • @belisarius你的测试条件是`> 1`,即快乐的数字将达到1,而不是不快乐的数字有些任意值.n步的最小值:s(5)= 7,s(6)= 356,s(7)= 78999.log 10(s(8))~975(= 78999/81).log 10(log 10(s(9)))~974.log 10(log 10(log 10(s(10))))〜974.因此9次迭代足以满足高达10 ^ 10 ^ 10 ^ 974`或者` 10 ^ 10 ^ 974`位数.我想我错过了一步. (2认同)

Joh*_*ooy 19

GolfScript - 64个字符(适用于1)

~:@.{0\`{15&.*+}/}*1=!"happy sad "6/=@,{@\)%!},,2=4*"non-prime">
Run Code Online (Sandbox Code Playgroud)

该程序进行n迭代以确定数字的幸福感,这对于大数字来说是非常浪费的,但是代码高尔夫不是为了节省除字符之外的资源.黄金测试同样是低效的-将n通过所有的值1,以n包容和检查恰好有与零剩余两个值.因此,虽然它在理论上是正确的,但是在真实计算机上运行非常大的数字是不实际的

GolfScript - 63个字符(1个失败)

~:@9{0\`{15&.*+}/}*1=!"happy sad "6/=@,2>{@\%!},!4*"non-prime">
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 13

Python - 127个字符

此时击败两个perl答案!

l=n=input()
while l>4:l=sum(int(i)**2for i in`l`)
print['sad','happy'][l<2],'non-prime'[4*all(n%i for i in range(2,n))*(n>1):]
Run Code Online (Sandbox Code Playgroud)

我还把这个答案移植到了GolfScript上,它只有1/2的大小!

  • 在第一次'for`之前,我从来不知道不需要空间. (4认同)
  • @Seth:大多数压缩算法都有一些小的开销,因此在压缩微小文件时很痛苦. (2认同)

oll*_*llb 12

C#,380 378 374 372 364 363 315 280 275 274 Chars

通过用嵌套循环替换递归函数,我能够将笔画数量提高到280(比原始值小100).

class P{static void Main(string[]a){var s=new System.Collections.Generic.HashSet<int>();int n=int.Parse(a[0]),p=n>1?4:0,c,d=1;for(;++d<n;)if(n%d<1)p=0;for(;n>1&s.Add(n);n=c)for(c=0;n>0;c+=d*d,n/=10)d=n%10;System.Console.Write((n>1?"sad":"happy")+" non-prime".Remove(1,p));}}
Run Code Online (Sandbox Code Playgroud)

这是空白:

class P
{
    static void Main(string[] a)
    {
        var s = new System.Collections.Generic.HashSet<int>();
        int n = int.Parse(a[0]),
            p = n > 1 ? 4 : 0,
            c,
            d = 1;
        // find out if the number is prime
        while (++d < n)
            if (n % d < 1)
                p = 0;
        // figure out happiness
        for (; n > 1 & s.Add(n); n = c)
            for (c = 0; n > 0; c += d * d, n /= 10)
                d = n % 10;

        System.Console.Write(
            (n > 1 ? "sad" : "happy")
            + " non-prime".Remove(1,p)
            );
    }
}
Run Code Online (Sandbox Code Playgroud)


mvd*_*vds 9

C,188 187 185 184 180 172 171 165

h(c,C,r,p){for(;C>1&&C%++p;);for(;c;c/=10)r+=c%10*(c%10);r&~5?h(r,C,0,1):printf(
"%s %sprime",r-1?"sad":"happy",p>=C&C>1?"":"non-");}main(c){h(c,c,0,scanf("%d",&c));}

$ ./a.out
139
happy prime

$ ./a.out
2
sad prime

$ ./a.out
440
happy non-prime

$ ./a.out
78
sad non-prime
Run Code Online (Sandbox Code Playgroud)

这是一个永远不会发出的递归函数,return但要么自己调用,要么在完成时打印输出.递归函数对平方数字求和,并确定两个for循环中的素数.scanf返回1作为参数放置h(),保存一个;和一个1(并且代价是必须使用前缀++p而不是后缀p++,p>C而不是p>=C)

r&~501 4 5,它的1指示快乐和别人的忧伤.

下一次尝试:删除h()并进行main()递归.


Rob*_*let 9

Python 2.6:194 180个字符,4行

import re
s=lambda n,l:0if n==1 else n in l or s(sum(int(a)**2for a in str(n)),l+[n])
n=input()
print['happy','sad'][s(n,[])],'non-'*bool(re.match(r'1?$|(11+?)\1+$','1'*n))+'prime'
Run Code Online (Sandbox Code Playgroud)

词法分析器能够分裂0if2for分成两个令牌,每个是一个惊喜给我:)(它不与工作else虽然)

函数s(悲伤)是递归的,并且接收循环中先前数字的列表作为其第二参数.原始性使用正则表达式技巧在线测试.

通过使用弃用的`n`语法而不是str(n),可以进一步减少4个字符的字符数,但我选择不使用它.

  • +1,素数的正则表达式非常好! (3认同)

hob*_*bbs 8

Perl,140个字符

sub h{$_==1&& happy||$s{$_}++&& sad
||do{$m=0;$m+=$_**2for split//;$_=$m;&h}}$n=$_=pop;
die h,$",(1x$n)=~/^1?$|^(11+?)\1+$/&&"non-","prime\n"
Run Code Online (Sandbox Code Playgroud)

换行是可选的.


gno*_*ice 7

MATLAB 7.8.0(R2009a) - 120个字符

添加了空格,换行符和注释以提高可读性

n=input('');
s=n;
c={'happy ','sad ','non-'};
while s>6,
  s=int2str(s)-48;
  s=s*s';                    %'# Comment to fix code highlighting
end;
disp([c{[s<2 s>1 ~isprime(n)]} 'prime'])
Run Code Online (Sandbox Code Playgroud)


Chu*_*bas 5

Ruby 1.9

169 168 146个字符

 h={1=>'happy'};s=->x{y=0;(y+=(x%10)**2;x/=10)while x>0;h[y]||(h[y]='sad';s[y])}
 $><<s[n=$*[0].to_i]+" #{'non-'if '1'*n=~/^1?$|^(11+?)\1+$/}prime"
Run Code Online (Sandbox Code Playgroud)

如果我们使用p而不是$><<代码,则缩短2个字符

用法:

$ ruby​​ happyprime.rb 139 happy prime $ ruby​​ happyprime.rb 2悲伤素数


非高尔夫:

hash = {1->'happy'}
is_happy = lambda do |number|
  #sum = number.scan(/\d/).reduce(0){|acum, digit| acum + digit.to_i ** 2 }
  sum=0; 
  while (number > 0)
      sum+= (number%10)**2
      number/=10
  end
  return hash[sum] if hash[sum] # If 1, or if cycled and hash contains the number already
  h[sum] = 'sad'
  return is_happy.call(sum)
end
number = ARGV[0].to_i
string = ""
string += is_happy.call(number) # either 'happy' or 'sad'
string += is_prime(number) ? " non-prime" : "prime"
puts string
Run Code Online (Sandbox Code Playgroud)

将该is_prime方法留给读者的练习;)

  • 很好地使用正则表达式作为素性检查! (3认同)

Tho*_*ing 5

哈斯克尔172

h s n|n`notElem`s=h(n:s)$sum[read[k]^2|k<-show n]|1`elem`s="happy "|0<1="sad "
c n|n<2||any((0==).mod n)[2..n-1]="non-"|0<1=[]
y n=h[]n++c n++"prime"
main=readLn>>=putStr.y
Run Code Online (Sandbox Code Playgroud)


Tho*_*ing 5

Javascript 244 250

function h(n){p=n=n<2?10:n;a=",";w="";s=[];while((y=a+s.join(a)+a).indexOf(a+n+a)<0){s.push(n);k=""+n;n=0;for(i=0;i<k.length;)c=k.charAt(i++),n+=c*c}w+=y.indexOf(",1,")<0?"sad ":"happy ";for(i=2;i<p;)p=p%i++?p:0;w+=p?"":"non-";return w+"prime"}
Run Code Online (Sandbox Code Playgroud)

上面的代码应在浏览器中运行,无需额外花哨的功能和特性(如Array.prototype.indexOf[]符号的字符串),但我还没有火狐之外进行了测试.

请注意,所有这些n都是全局变量(我只是便宜).

用法

h(139) // returns "happy prime"
Run Code Online (Sandbox Code Playgroud)

  • 很好,我不得不在最后添加一个`}`,但这可能是因为我使用的是Firefox的Web控制台.我印象深刻的是Javascript和你的代码能够处理`h(2535301200456458802993406410753)`! (2认同)