Finde die kleinste Primzahl aus einem Teilstring

17

Erdos und Copeland haben 1946 bewiesen, dass eine bestimmte Zahl eine normale Zahl ist , dh die Ziffern in ihrer Dezimalerweiterung sind gleichmäßig verteilt.

Die Benutzer geben eine Ziffernfolge ein, und Sie finden die kleinste Primzahl, die diese Zeichenfolge enthält, in Basis 10.

Beispiel:

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

Kürzester Code in Bytes gewinnt. Ich weiß, dass einige Sprachen (Mathematica, Salbei, Pari-GP ...) eingebaute Funktionen haben, die sich auf Primzahlen beziehen. -50 Bytes, wenn Ihr Programm nicht auf solche Funktionen angewiesen ist. Versuchen Sie nicht, dies zu betrügen. Wenn Ihre Sprache bereits einen großen Vorteil hat, fordern Sie den Bonus nicht an.

Bearbeiten

Nach einigen Kommentaren ist die kleinste Primzahl, die "03" enthält, 3. Macht dies wirklich einen Unterschied? Das Einzige, woran ich denken kann, ist, dass Zahlen möglicherweise einfacher zu handhaben sind als Zeichenfolgen.

In Fällen wie "03" wäre die bevorzugte Ausgabe 103. Ich halte sie jedoch nicht für den grundlegenden Teil Ihres Programms, so dass Sie jede führende Null ignorieren können, wenn sie Ihnen eine niedrigere Byteanzahl gewährt.

Izabera
quelle
5
Dies scheint eine gute Basis für eine Projekt-Euler-Aufgabe zu sein
John Dvorak
Die kleinste Primzahl, die "03" enthält, ist 03. Vielleicht sollten Sie eine Regel hinzufügen, die klarstellt, dass die Eingabe möglicherweise führende Nullen enthält, die Ausgabe jedoch nicht.
Level River St
2
@steveverrill Es gibt keine Nummer wie 03. Wenn Sie 3 gemeint haben, dann enthält das nicht "03".
John Dvorak
3
@JanDvorak 03 ist eine gültige Darstellung der Zahl 3. (2,9 ... unendlich oft wiederkehrend, entspricht 2 + 9/9, wird auch von einigen als gültige Darstellung angesehen.) Aus dem gegebenen Beispiel geht hervor, dass 03 nicht akzeptabel ist Darstellung für diese Frage. Dies ist ein pedanter Punkt, aber angesichts des üblichen Missbrauchs der Regeln, den ich für wert halte.
Level River St
1
Ich denke, der bessere Weg, es auszudrücken, wäre, die kleinste Zahl zu finden, die, wenn sie in eine Zeichenkette umgewandelt wird, "03" enthält.
Thebluefish

Antworten:

13

Golfscipt, 33 32 Bytes = -18 Punkte

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

Erläuterung:

  • 2{...}{)}/- beginnend mit 2, während etwas wahr ist, erhöhen Sie die Oberseite des Stapels
  • ;;x- die von {}{}/und die Eingabe gesammelten Zwischenwerte verwerfen und den zuletzt getesteten Wert dort ablegen

  • :x,2>- Speichern Sie den Wert als x, und erstellen Sie eine Liste von 2bisx-1

  • {x\%!},!!- Behalte diejenigen, xdie durch teilbar sind, und zwinge sie dann zum Booleschen (nicht leer)
  • x`3?)!- Nachschlagen der Eingabe in der Textform x( -1falls nicht gefunden), Inkrementieren, Negieren.
  • | - oder
John Dvorak
quelle
7

Haskell-Programm, 97 Zeichen = 47 Punkte

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

Haskell-Funktion, 75 Zeichen = 25 Punkte

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

die Art pist (Integral a, Show a) => [Char] -> a. Wenn Sie einen eigenen ganzzahligen Typ angeben, können Sie diese Werte in Ihrer eigenen Darstellung nachschlagen. Der Standard Integerverwendet die erwartete Dezimalschreibweise für Ganzzahlen.

Nicht sehr schnell. Quadratisch im Wert (nicht in der Größe) der Ausgabe.

ungolfed version:

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

Beispiel:

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
John Dvorak
quelle
3

Java - 175 Zeichen.

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++;}}}
Platzhalter
quelle
Sie können 1 Zeichen speichern, indem Sie das Leerzeichen zwischen indexOf(a[0])>=0)und entfernen {System.out.println(n).
ProgramFOX
@ProgramFOX Danke.
Wildcard
Ich denke, Sie können leicht (ungefähr 8) Zeichen speichern, indem Sie Ihr Zeichen durch so boolean p=trueetwas wie int p=1usw. ersetzen .
Florian h
Wenn Sie alle Eingaben auf einmal deklarieren, wird die Programmgröße weiter reduziert.
Olivier Grégoire
3

Mathematica 58

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

Relative Timings auf meinem Mac (2,6 GHz i7 mit 8 GB Speicher).

Finde die kleinste Primzahl mit "01".

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

{0,000217, 101}


Finde die kleinste Primzahl mit "012345".

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

{5.021915, 10123457}


Finde die kleinste Primzahl mit "0123456".

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

{87.056245, 201234563}

DavidC
quelle
Sie können verwenden StringFreeQ, um es kürzer zu machen.
Alephalpha
2

Salbei , 72

Läuft in der interaktiven Eingabeaufforderung

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

Primes().unrank(i)gibt die ith Primzahl an, wobei die 0th Primzahl 2 ist.

user12205
quelle
2

R, 56 Zeichen - 50 = 6

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

Eingabe als stdin übernehmen. Inkremente k bis k ist eine Primzahl (getestet durch Summieren der Instanzen, für die k mod 2 bis k Nullen sind, daher FALSE, da 0 zu einer logischen ist FALSE) und enthält den als Eingabe gegebenen String (getestet mit einem einfachen grep, hier grepl da wir ein logisches als Ergebnis wollen).

Verwendung:

> 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
Plannapus
quelle
2

Shell Oneliner (Coreutils): 45 Zeichen

Hier wird keine Funktion definiert ... nur ein Oneliner, der ein Argument aufnimmt $nund den Integer-Bereich abtastet (eigentlich ein bisschen mehr, um den Code zu verkürzen). Die 55-stellige Version:

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

Es ist nicht einmal zu langsam. Denn n=0123456es kehrt 201234563in 81.715s. Das ist beeindruckend schnell für eine lange Pipeline mit zwei String-Prozessoren.

Wenn wir zwei Zeichen (bis zu 53) und eine Pipe entfernen, können wir es noch schneller zum Laufen bringen:

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

Und zum Schluss ein sedbisschen Zauberei, um es auf 45 Zeichen zu bringen , obwohl der Ausdruck hässlich ist:

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

n = 000 -> 10007: 10007 (Benutzer 0.017s)

n = 012345 -> 10123457: 10123457 (Benutzer 7.11s)

n = 0123456 -> 201234563: 201234563 (Benutzer 66,8s)

orion
quelle
2

J - 38 Zeichen -50 = -12 Punkte

Normalerweise würden Sie in J die sehr optimierten Buildins für Primzahlen verwenden, sodass ich mich nicht für langsame Ausführung entschuldigen werde.

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

Erklärt:

  • >:@]^:(...)^:_&2- Beginnen Sie mit 2 und erhöhen Sie, bis (...)false zurückgegeben wird.
  • (+.i.)@]- Nehmen Sie die GCD des Zählers mit jeder kleineren Ganzzahl. (Wir verwenden die Konvention GCD (X, 0) = X.)
  • ]=*/@- Nehmen Sie das Produkt aus all diesen Zahlen und prüfen Sie, ob es mit dem Zähler übereinstimmt. Wenn der Zähler prim ist, war die Liste alle 1s, mit Ausnahme der GCD mit 0; Andernfalls ist mindestens eine GCD größer als 1, sodass das Produkt größer als der Zähler ist.
  • >./@(E.":)- Prüfen Sie, ob die Zeichenfolgendarstellung des Zählers ":( E.) an einer beliebigen Stelle die Zeichenfolge ( ) enthält . >./ist die Max-Funktion, und wir verwenden es, weilE. einen booleschen Vektor mit einer 1 zurückgibt, wo immer der Teilstring im Hauptstring beginnt.
  • *:- Logisch und die Ergebnisse zusammen. Dies ist nur dann falsch, wenn beide Eingaben wahr sind, dh wenn der Zähler prim war und die Teilzeichenfolge enthielt.

Verwendung:

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

Für die Nachwelt ist hier die Version mit dem eingebauten Prime (30 Zeichen lang, aber ohne Bonus):

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

1 p:] Testet den Zähler auf Primalität anstelle des GCD-Tricks.

algorithmshark
quelle
2

Brachylog (v2), 3 Bytes in der Brachylog-Codierung

ṗ≜s

Probieren Sie es online!

Funktionsübergabe, Eingabe aus dem rechten Argument, Ausgabe durch Mutation des linken Arguments. (Dies ist das Gegenteil der normalen Brachylog-Konvention. Weitere Informationen finden Sie in diesem Metapost . Das Vertauschen der Argumente in die üblichere Reihenfolge kostet drei Bytes.) Der TIO-Link verfügt über einen Wrapper, der die Funktion mit der entsprechenden Aufrufkonvention aufruft und druckt das Ergebnis.

Erläuterung

ṗ≜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}

Leider ist Brachylog für dieses Problem so geeignet, dass ich nach den Regeln des Problems nicht einmal versuchen kann, den Bonus zu bekommen (was ironischerweise bedeutet, dass er nicht gewinnen kann).

Einer der Gründe, warum ich Brachylog so sehr mag, ist, dass Programmierung eine Kommunikation zwischen Mensch und Computer ist und daher in einer "perfekten" Sprache die Problemspezifikation direkt ins Englische übersetzt werden kann. Die Ideen, über die das Problem festgestellt wurde und über die das Programm geschrieben wird, wären die gleichen. Brachylog kann dieses Ideal überraschend oft treffen; Die Frage lautet hier "Finde die kleinste Primzahl, die einen bestimmten Teilstring enthält", und ich kann die Begriffe "kleinste Primzahl, die einen Teilstring enthält" buchstäblich in der richtigen Reihenfolge aneinanderreihen und ein funktionierendes Programm haben. Als solches sagt Brachylog viel mehr über die Natur der Kommunikation aus als eine Sprache, in der Sie explizit einen Algorithmus zur Lösung des Problems spezifizieren müssten; manchmal, wenn mit anderen Menschen gesprochen wird, Wir versuchen, ein Problem zu erklären, indem wir die Schritte erläutern, die Sie unternehmen würden, um es zu lösen. Dies ist jedoch selten. Warum sollten unsere Sprachen anders sein?

ais523
quelle
1

JavaScript 83 Bytes = 33 Punkte

Golf gespielt:

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)

Ungolfed (ein bisschen):

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)
DocMax
quelle
0

Javascript (Node.JS) - 93 Bytes = 43 Punkte

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

In extrahierter Form mit sinnvollen Variablennamen:

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

Rust 0,9 136 Bytes = 86 Punkte

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);
}

Trotz der Kompaktheit sehr deutlich. Zu viel Platz für die Suche nach Saiten. :(

Hier die Version ohne Leerzeichen (136 Zeichen)

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);}
Ilmale
quelle
0

Perl 6 , 36 - 50 = -14 Punkte

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

Probieren Sie es online!

Berücksichtigt $_%%one ^$_wird, dass nur 2 Bytes kleiner als sind.is-prime , denke ich, dass es sich für den Bonus lohnt. Dies ist eine Zeitüberschreitung für den letzten Testfall.

Erläuterung:

{                                  }  # Anonymous code block
 $^a;                                 # Assign input to $a
     first                    ,2..*   # Find the first number
           {                 }        # Which
            /$a/                        # Contains the input
                &&                      # And
                  $_%%one ^$_           # Is prime
Scherzen
quelle
2 Bytes kleiner?
Nur ASCII
lol @ the Teil in der Frage, die sagt "Versuchen Sie nicht, dies zu betrügen, bitte, wenn Ihre Sprache bereits einen großen Vorteil hat, fordern Sie nicht den Bonus."
Nur ASCII
@ Nur ASCII Nun, ich werde immer noch von GolfScript geschlagen, also ...:$
Jo King
0

Python 3 , 80 79 Bytes - 50 = 30 29 Punkte

-1 Byte dank der kreativen Verwendung von @ ASCII-only %sanstelle vonstr

Der Testfall "98765" wurde noch nicht bestätigt, da der Test erst nach ein paar Stunden durchgeführt werden kann. Der Testfall "98765" wurde bestätigt. Bei einem ähnlichen Ansatz, bei dem eine Kurzschlussbewertung verwendet wird, um einige Primärtests zu vermeiden, funktioniert der Test viel schneller. Alternativ kann dies ~ 2x so schnell sein, wenn wir wissen, dass "2" keine Eingabe ist (wir können es vermeiden, gerade Zahlen auf Primalität zu prüfen), indem Sie i=3anfänglich und i+=2in der Schleife ohne zusätzliche Bytekosten festlegen.

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

Probieren Sie es online!

Erläuterung der whileBedingung ((x in"%s"%i)*all(i%j for j in range(2,i))-1 ):

(x in"%s"%i): True/ 1wenn der aktuelle Zähler die gewünschte Zahlenfolge enthält; False/0 ansonsten.

all(i%j for j in range(2,i)): True/ 1wenn der aktuelle Zähler immer einen Rest hat, wenn er durch eine beliebige Ganzzahl von 2 (einschließlich) bis zu sich selbst (ausschließlich) geteilt wird, dh eine Primzahl ist; False/0 ansonsten.

Das *multipliziert die beiden Bedingungen und agiert als andOperator - das Produkt ist True/ 1wenn und nur wenn beide Bedingungen sind True/1 .

Das -1wirkt als notOperator: False/ 0- 1 ergibt -1, was als wahr angesehen wird, wohingegen True/ 1- 1 ergibt0 , was als falsch gilt. Somit wird die Schleife fortgesetzt, während die Zahl entweder nicht die gewünschte Folge von Zahlen enthält oder keine Primzahl ist.

Ersetzen Sie das *mit andund setzen Sie Klammern um alles außer dem-1 um eine viel schnellere, gleichwertige Lösung zu erhalten (die etwas länger ist).

Eine 76-Byte- Lösung mit 50 = 26 Punkten in Python 2, die nur von @ ASCII angegeben wird (verwendet ``anstelle von str(),

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

Probieren Sie es online!

Neil A.
quelle
@ Nur ASCII Ich habe nicht viel mit Python 2 gearbeitet und benutze meistens Python 3, also spiele ich Golf. Obwohl es so aussieht, als wäre Python 2 die meiste Zeit kürzer ...
Neil A.
Du hast einen Tippfehler gemacht, in dem ersten hast dureturn I
ASCII
79
Nur ASCII