从子串中找到最小的素数


17

1946年,鄂尔多斯和科普兰证明某个数字是一个正数,即其十进制扩展中的数字是均匀分布的。

用户将输入一个数字序列,您会发现以10为底的包含该字符串的最小素数。

例:

input   -> output
"10"    -> 101
"03"    -> 103
"222"   -> 2221
"98765" -> 987659

以字节为单位的最短代码获胜。我确实知道某些语言(mathematica,sage,pari-gp ...)带有与质数有关的内置函数。-50字节(如果您的程序不依赖于此类功能)。如果您的语言已经具有巨大的优势,请不要试图对此作弊,不要索取奖金。

编辑

根据下面的一些评论,包含“ 03”的最小素数为3。这真的有区别吗?我唯一想到的是,数字可能比字符串更容易处理。

在“ 03”之类的情况下,首选输出为103。但是,我不认为它是程序的基础部分,因此,如果它允许您减少字节数,则可以随意忽略任何前导零。


5
这似乎是Euler项目任务的良好基础
John Dvorak 2014年

包含“ 03”的最小素数为03。也许您应该添加一条规则,以澄清输入可能包含前导零,但输出可能不包含。
级圣河

2
@steveverrill没有数字03。如果您的意思是3,则其中不包含“ 03”。
John Dvorak 2014年

3
@JanDvorak 03是数字3的有效表示形式。(2.9 ...无限地重复出现,等效于2 + 9/9,也被某些有效表示形式认为是。)我从示例中了解到,03是不可接受的此问题的表示形式。这是一个讲究的观点,但是考虑到通常会违反规则,我认为值得提出。
级圣河

1
我认为更好的表达方式是找到转换为字符串时包含“ 03”的最小数字。
Thebluefish 2014年

Answers:


13

Golfscipt, 33 32个字节= -18分

2{:x,2>{x\%!},!!x`3$?)!|}{)}/;;x

说明:

  • 2{...}{)}/-以开头2,当某些情况成立时,增加堆栈顶部
  • ;;x-丢弃由{}{}/和收集的中间值,然后将最后测试的值放在此处

  • :x,2>-存储的值x,然后产生一个名单2x-1

  • {x\%!},!!-保留那些可x被整除的变量,然后强制转换为布尔值(不为空)
  • x`3?)!-以x-1如果找不到),递增,取反的文本形式查找输入。
  • | - 要么

7

Haskell程序,97个字符= 47分

main=getLine>>= \i->print$head$[x|x<-[2..],all((/=0).mod x)[2..x-1],i`Data.List.isInfixOf`show x]

Haskell函数,75个字符= 25分

p i=head$[x|x<-[2..],all((/=0).mod x)[2..x-1],i`Data.List.isInfixOf`show x]

的类型p(Integral a, Show a) => [Char] -> a。如果提供自己的整数类型,则可以按自己的那些值表示形式中的infix查找。该标准Integer对整数使用期望的十进制表示法。

不太快。输出值(而非大小)的平方。

非高尔夫版本:

import Data.List
leastPrime infix = head $ filter prime' [2..]
  where prime' x  = all (\n-> x`mod`n /= 0) [2..x-1]
                 && i `isInfixOf` show x
main = print . leastPrime =<< getLine

例:

Prelude> let p i=head$[x|x<-[2..],all((/=0).mod x)[2..x-1],i`Data.List.isInfixOf`show x]
Prelude> p "0"
101
Prelude> p "00"
1009
Prelude> p "000" -- long pause
10007

3

Java-175个字符。

class s{public static void main(String[]a){int i,n=2,p;for(;;){p=1;for(i=3;i<n;i++)if(n%i==0)p=0;if((n==2||p>0)&&(""+n).indexOf(a[0])>=0) {System.out.println(n);break;}n++;}}}

您可以通过之间的下探空间节省1个字符indexOf(a[0])>=0){System.out.println(n)
ProgramFOX 2014年

@ProgramFOX谢谢。
通配符

我认为您可以boolean p=true通过类似的替换您的字符来轻松保存(大约8个)字符int p=1
florian h 2014年

一次声明所有int将进一步减小程序大小。
OlivierGrégoire2014年

3

Mathematica 58

(n=1;While[StringCases[ToString[p=Prime@n],#]=={},n++];p)&

我的Mac上的相对时序(2.6 GHz i7,8 GB内存)。

找到包含“ 01”的最小素数。

AbsoluteTiming[(n = 1; While[StringCases[ToString[p = Prime@n], #] == {}, n++]; p) &["01"]]

{0.000217,101}


找到包含“ 012345”的最小素数。

AbsoluteTiming[(n = 1; While[StringCases[ToString[p = Prime@n], #] == {}, n++]; p) &["012345"]]

{5.021915,10123457}


找到包含“ 0123456”的最小素数。

AbsoluteTiming[(n = 1; While[StringCases[ToString[p = Prime@n], #] == {}, n++]; p) &["0123456"]]

{87.056245,201234563}


您可以使用StringFreeQ它来使其更短。
alephalpha 2014年

2

贤者,72

在交互式提示中运行

a=raw_input()
i=0
p=2
while a not in str(p):i+=1;p=Primes().unrank(i)
p

Primes().unrank(i)给出i第素数,第0个素数为2。


2

R,56个字符-50 = 6

k=2;n=scan(,"");while(!grepl(n,k)|sum(!k%%2:k)>1)k=k+1;k

将输入作为标准输入。递增k直到k为质数(通过将k mod 2到k为零的实例相加进行测试,由于从0变成逻辑为FALSE,因此为FALSE),并且包含作为输入提供的字符串(使用简单的grep测试,此处为grepl)因为我们想要一个合乎逻辑的结果)。

用法:

> k=2;n=scan(,"");while(!grepl(n,k)|sum(!k%%2:k)>1)k=k+1;k
1: "03"
2: 
Read 1 item
[1] 103
> k=2;n=scan(,"");while(!grepl(n,k)|sum(!k%%2:k)>1)k=k+1;k
1: "003"
2: 
Read 1 item
[1] 2003

2

Shell oneliner(coreutils):45个字符

这里没有定义函数...只是一个内联函数,它接受一个参数$n并扫描整数范围(实际上要多一点以使代码更短)。55个字符的版本:

seq 5e9|grep $n|factor|awk '{if(NF==2)print $2}'|head -n1

它甚至还不太慢。对于n=0123456它返回20123456381.715s。对于带有两个字符串处理器的长管道来说,这是惊人的快。

删除两个字符(最多53个)和一个管道,我们可以使其运行得更快:

seq 5e9|grep $n|factor|awk '{if(NF==2){print $2;exit}}'

最后,尽管打印输出很丑陋,但还是有些sed巫术将其减少到45个字符

seq 5e9|grep $n|factor|sed -n '/: \w*$/{p;q}'

n = 000-> 10007:10007(用户0.017s)

n = 012345-> 10123457:10123457(用户7.11s)

n = 0123456-> 201234563:201234563(用户66.8s)


2

J-38个字符-50 = -12分

通常在J中,您将使用专门针对素数的非常优化的内置函数,因此我不会为执行中的任何缓慢而道歉。

>:@]^:(>./@(E.":)*:]=*/@(+.i.)@])^:_&2

解释:

  • >:@]^:(...)^:_&2-从2开始,递增直到(...)返回false。
  • (+.i.)@]-取每个小于它的整数的GCD。(我们使用约定GCD(X,0)=X。)
  • ]=*/@-取所有这些数字的乘积,并测试是否相等。如果计数器是质数,则列表全为1,但GCD为0;否则为0。否则至少会有一个大于1的GCD,因此乘积将大于计数器。
  • >./@(E.":)-测试计数器(":)的字符串表示形式是否E.在任何时候都包含字符串()。>./是max函数,我们之所以使用它是因为E.无论子字符串在主字符串中的何处开始,它都返回一个带有1的布尔向量。
  • *:-将逻辑NAND结果结合在一起。仅当两个输入均为true时,即计数器均为质数且包含子字符串的计数器时,此参数才为false。

用法:

   >:@]^:(>./@(E.":)*:]=*/@(+.i.)@])^:_&2 '03'
103
   >:@]^:(>./@(E.":)*:]=*/@(+.i.)@])^:_&2 '713'
2713

为了后代,这是使用主要内置函数的版本(长30个字符,但无奖金):

>:@]^:(>./@(E.":)*:1 p:])^:_&2

1 p:] 测试计数器的原始性,而不是GCD技巧。


2

Brachylog(v2),采用Brachylog编码的3个字节

ṗ≜s

在线尝试!

函数提交,从右侧参数获取输入,通过更改左侧参数提供输出。(这与常规的Brachylog约定相反;有关更多讨论,请参见此meta帖子。将参数交换为更通常的顺序将花费三个字节。)TIO链接具有一个包装器,该包装器使用适当的调用约定来调用该函数并进行打印结果。

说明

ṗ≜s
 ≜   Find the integer closest to zero
ṗ      which is prime {implicit: and output it via the left argument}
  s    and which is a substring of the {right argument}

可悲的是,Brachylog非常适合该问题,根据问题中的规则,我什至无法尝试获得奖金(具有讽刺意味的是,它无能为力)。

我之所以喜欢Brachylog的原因之一是编程是人与计算机之间的交流,因此“完美”的语言可以让您直接将问题说明翻译成英语。陈述问题和编写程序的思路是相同的。Brachylog经常会令人惊讶地达到这一理想;这里的问题是“找到包含给定子串的最小素数”,我可以按照正确的顺序将“最小,素数,包含子串”的概念串起来,并有一个有效的程序。因此,Brachylog对通信的本质的说明远不止于您必须明确指定用于解决问题的算法所用的语言。有时候和其他人说话时 我们尝试通过解释解决问题的步骤来解释问题,但这很少见。那么为什么我们的语言应该有所不同呢?


1

JavaScript 83字节= 33分

打高尔夫球:

for(s=prompt(n=x=0);!n;x++)for(n=(''+x).match(s)?2:0;n&&n<x;n=x%n?n+1:0);alert(x-1)

松散(一点点):

s=prompt() // get the input
n = 0
for(x=0;!n;x++) // stop when n is non-zero
    if ((''+x).match(s)) { // if x matches the pattern, check if x is prime
        for(n=2;n&&n<x;)
            n = (x%n == 0) ? 0 : n+1; // if x%n is zero, x is not prime so set n=0
        // if n is non-zero here, x is prime and matches the pattern
    }
alert(x-1)

0

Javascript(Node.JS)-93字节= 43点

l:for(i=x=process.argv[2];j=i;i++){while(--j>2)if(!(i%j*(""+i).match(x)))continue l
throw i}

以具有合理变量名的提取形式:

outerLoop:for (currentTry=inputNumber=process.argv[2]; primeIterator=currentTry; currentTry++ ) {
    while (--primeIterator > 2) 
        if(!(currentTry % primeIterator * (""+currentTry).match(inputNumber)))
            continue outerLoop;
    throw i
}

0

Rust 0.9 136字节= 86分

fn main(){
   let mut n:u32=2;
   while n.to_str().find_str(std::os::args()[1])==None ||
         range(2,n).find(|&x|n%x==0)!=None {
      n=n+1;
   }
   print!("{}",n);
}

尽管很紧凑,但非常明确。在字符串查找上花费了太多空间。:(

这里没有空格的版本(136个字符)

fn main(){let mut n:u32=2;while n.to_str().find_str(std::os::args()[1])==None||range(2,n).find(|&x|n%x==0)!=None{n=n+1;}print!("{}",n);}



0

Perl 6,36-50 = -14点

{$^a;first {/$a/&&$_%%one ^$_},2..*}

在线尝试!

考虑$_%%one ^$_到仅比 2个字节.is-prime,我认为这是值得的。最后一个测试用例超时。

说明:

{                                  }  # Anonymous code block
 $^a;                                 # Assign input to $a
     first                    ,2..*   # Find the first number
           {                 }        # Which
            /$a/                        # Contains the input
                &&                      # And
                  $_%%one ^$_           # Is prime

小2个字节?
ASCII码,仅ASCII,

大声笑@问题中的部分,内容为“请勿尝试对此作弊,如果您的语言已经具有巨大的优势,请不要索取奖金。”
ASCII码,仅ASCII,

@ASCII only –好吧,我仍然被GolfScript击败,所以……:$
Jo King

0

Python 3中80 79个字节- 50 = 30 29评分

-1字节归功于@ ASCII-only的创造性使用,%s而不是str

测试用例“ 98765”尚未确认,因为测试需要多长时间,几个小时后就确认了测试用例“ 98765”,但是采用类似的方法,利用短路评估来避免某些素数测试,因此可以正常工作快多了。另外,如果我们知道“ 2”不是输入(我们可以避免在偶数中检查素数),则可以通过设置i=3初始值和i+=2在循环中进行设置,而速度却快2倍左右,而不会产生额外的字节开销。

def f(x):
 i=2
 while(x in"%s"%i)*all(i%j for j in range(2,i))-1:i+=1
 return i

在线尝试!

while条件((x in"%s"%i)*all(i%j for j in range(2,i))-1)的说明:

(x in"%s"%i)True/ 1如果当前计数器包含在它数的所需序列; False/ 0否则。

all(i%j for j in range(2,i))True/ 1如果当前计数器总是具有当由任何整数2(含)除以剩余部分本身(不包括),即是素数; False/ 0否则。

*相乘的两个条件一起,并作为一个and操作员-该产品是True/ 1当且仅当两个条件都True/ 1

-1充当not操作员:False/ 0- 1次的结果中-1,这被认为是真实的,而True/ 1- 1次的结果中0,这被认为是错误的。因此,循环继续进行,而数字要么不包含所需的数字序列,要么不是质数。

替换为*and并在除之外的所有内容周围加上括号-1,以得到更快,等效的解决方案(稍长一些)。

Python 2中一个76字节-50 = 26的分数解决方案,由@ ASCII-only给出(使用``代替str()

def f(x):
 i=2
 while(x in`i`)*all(i%j for j in range(2,i))-1:i+=1
 return i

在线尝试!



@only ASCII代码,我没有使用python 2太多,大部分都使用python 3,所以这就是我的目标。尽管似乎大多数时候python 2最终都变短了……
Neil A.

您输入了错字,在第一个输入错了return I
ASCII码,仅ASCII,2009年


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.