Finden Sie die größte zusammenhängende Primzahl in einer Zeichenfolge

8

Fairerweise basiert dies auf einer StackExchange-Frage - aber es ist eine gute Frage.

Die Herausforderung ist ziemlich einfach:

  1. Nehmen Sie eine Reihe von Ziffern
  2. Suchen und drucken Sie die größte zusammenhängende Primzahl in der Zeichenfolge

Wertung:

  • Die niedrigste Anzahl von Charakteren gewinnt.
  • Victor wird wahrscheinlich ein Golfscript-Eintrag sein, aber wir werden das nicht gegen sie aufbringen , weil wir alle Spaß haben und Dinge lernen, richtig.
  • Gewinner werden wir ausgezeichnet, wenn ich bemerke, dass ich den grünen Knopf nicht wirklich angekreuzt habe.

Annahmen:

  • Die Zeichenfolge besteht nur aus Zahlen
    • Wenn die Zeichenfolge Buchstaben enthält, liegt möglicherweise ein undefiniertes Verhalten vor
  • Die Zeichenfolge enthält mindestens 1 Primzahl
    • Wenn die Zeichenfolge keine gültige Primzahl enthält, liegt möglicherweise ein undefiniertes Verhalten vor
  • Geschwindigkeit ist keine Einschränkung
    • Verwenden Sie einen kürzeren Primalgorithmus gegenüber einem schnelleren.
    • Wenn Ihr Eintrag irgendwann fertig ist, ist das in Ordnung. Stellen Sie einfach sicher, dass dies nachweislich vor dem Hitzetod des Universums geschieht.
  • Die Länge der Zeichenfolge kann mit weniger als 15 Zeichen angenommen werden

Zum Beispiel:

>> Input:  3571
<< Output: 3571

>> Input:  123
<< Output: 23

>> Input:  1236503
<< Output: 236503

>> Input:  46462
<< Output:  2

>> Input:  4684
<< Output: ValueError: max() arg is an empty sequence

>> Input:  460
<< Output: 0   # Note, zero is not a prime, but the above string has no valid prime

>> Input:  4601
<< Output: 601

>> Input:  "12 monkeys is a pretty good movie, but not as good as se7en"
<< Output: ValueError: Fight Club was also good, I find Brad Pitt to be a consistantly good actor.

Mögliche Implementierungen:

  1. Suchen Sie alle Teilzeichenfolgen der Eingabe und prüfen Sie, ob sie Primzahlen sind. - Legostormtroopr (Original)
  2. Finden Sie alle Ganzzahlen, die kleiner als die Eingabe sind, prüfen Sie, ob sie in der Eingabe enthalten sind, und prüfen Sie, ob es sich um eine Primzahl handelt - Ben Reich
  3. Nehmen Sie eine Liste aller Primzahlen, die kleiner als die Eingabe sind, und prüfen Sie, ob sie in der Eingabe enthalten sind - daniero
Gemeinschaft
quelle
1
Dies scheint im Grunde wie folgt zu sein: Finden Sie eine Möglichkeit, über jeden Teilstring des Strings zu iterieren, und überprüfen Sie die Primalität des Teilstrings. Klingt nach einem lustigen Problem.
Justin
1
@ Quincunx Richtig. Aber ich wollte es so eindeutig wie möglich machen. Und auch Popkultur-Referenzen fallen lassen.
1
@ Quincunx Das ist jedoch nicht der einzig mögliche Algorithmus! Schauen Sie sich meine Antwort an, die wie folgt beschrieben werden kann: Iterieren Sie über alle Ganzzahlen, die kleiner als die Eingabe sind, und bestimmen Sie die größte, die sowohl eine Teilzeichenfolge der Eingabe als auch eine Primzahl ist.
Ben Reich
@BenReich Oder wie ich, iteriere über alle Primzahlen, die kleiner oder gleich der Eingabe in sind, und sehe, dass sie in der Zeichenfolge sind.
Daniero
1
Warum ist mir ein ausgeglichenes Spielfeld wichtig? Wir wissen, welche Skripte gewinnen, aber gewinnen ist nicht alles? Machen Sie den kürzesten und klügsten Code in Ihrer Lieblingssprache.

Antworten:

6

GolfScript 40 37

.{`\`?)}+\~),\,{.,(;\{\%!}+,,1=},)\;

Dies betrachtet alle Zahlen, die kleiner oder gleich der Eingabe sind, filtert bis zu denjenigen, die Teilzeichenfolgen der Eingabe sind, und filtert dann weiter bis zu den Primzahlen. Dann braucht es das größte derartige Element (das offensichtlich die meisten Ziffern hat).

Lassen Sie es uns in zwei Hauptabschnitte aufteilen:

.{`\`?)}+\~,\,

Dieser Teil des Codes filtert nach allen in der Eingabe enthaltenen Ganzzahlzeichenfolgen. Es verwendet einen starken Akzent, um Zahlen in Zeichenfolgen ?umzuwandeln und dann den Index der Teilzeichenfolge zu bestimmen. Da ?kehrt -1in dem Fall ohne Containment, inkrementierte verwendet , )so dass der Ausgang 0für nicht-substrings, die gut mit dem verhalten ,Filterung.

{.,(;\{\%!}+,,1=},

Dieser Teil des Codes wird auf die Primzahlen heruntergefiltert, indem die Anzahl der Faktoren gezählt wird, die kleiner als die angegebene Anzahl sind (eine Ganzzahl ist nur dann ein Faktor, wenn sie 1 number factor %!ist. Eine Primzahl hat genau 1 Faktor, der streng kleiner ist als sie selbst 1=.

Da die Zahlen in Ordnung sind, nehmen Sie die letzte und löschen Sie den Stapel mit )\;

Dies ist offensichtlich nicht so effizient wie möglich (da es unnötigerweise über alle Ganzzahlen iteriert, die kleiner als die Eingabe sind), aber es endet immer noch mit einer großen Eingabe wie 1236503relativ schnell auf meinem Computer (1 Minute).

Ben Reich
quelle
1
Dank dir habe ich fast so viele Antworten rasiert, wie du benutzt hast: P
1
Wenn es sich bei der Eingabe um eine Primzahl handelt, wird diese nicht gefunden, da der erste Filter auf Zahlen angewendet wird, die diese Zahl nicht enthalten. Der Fix kostet ein Zeichen, aber es müssen zwei Zeichen gespeichert werden, indem die Eingabe in einer Variablen gespeichert wird, anstatt mit dem Block zu verketten (da Sie auf diese Weise einige Flips eliminieren).
Peter Taylor
4

Python 2.7 - 84

Hier ist eine Referenzimplementierung, die es zu schlagen gilt. Ich habe sie für die Beispielausgabe in der Frage verwendet, daher ist garantiert, dass sie funktioniert. * Keine tatsächliche Garantie

Schamlose Verbesserung basierend auf Ben Reichs viel besserer Lösung als meine ursprüngliche. Mit großer Unterstützung von Volatility

N=input()
print max(x for x in range(N+1)if(`x`in`N`)&all(x%i for i in range(2,x)))

Frühere Beschwörungsformeln der zweiten Zeile umfassen:

print max(x for x in range(N+1)if`x`in`N`and 0 not in(x%i for i in range(2,x)))
print max(x for x in range(N+1)if`x`in`N`and sum(x%i<1 for i in range(2,x))<1)

Die Originalversion - 143

N=`input()`
p=lambda n:[n%i for i in range(2,n)if n%i==0]
print max(int(N[j:i])for i in range(len(N)+1)for j in range(i)if not p(int(N[j:i])))
Gemeinschaft
quelle
2
Werde los pund ersetze not p(x)durch sum(x%i for i in range(2,x))<1- es sollte funktionieren und bringt dich auf 86 Zeichen.
Volatilität
@Volatility Nicht ganz, sum(x%i for i in range(2,x))wird für die meisten Zahlen ziemlich hoch sein. Aber der Generator ist eine großartige Idee und ich habe sie auf 91 gebracht.
Eigentlich weißt du was, ich denke du kannst all(x%i for i in range(2,x))stattdessen verwenden.
Volatilität
Speichert noch einen, danke :)
Wechseln Sie zu allund (`x`in`N`)speichern Sie die Saves noch ein paar mehr!
1

Rubin 61

Nehmen Sie alle Primzahlen bis N und prüfen Sie, ob sie in der Zeichenfolge enthalten sind

require'prime'
p Prime.each(gets.to_i).select{|i|~/#{i}/}.max

Ich denke, das funktioniert nur unter Ruby 1.9 und neuer, bin mir aber nicht sicher.

daniero
quelle
Was gibt Ihr Programm für das letzte Testbeispiel zurück? Die Primzahl 2 ist drin, sollte aber nicht erkannt werden (wenn ich die Anforderungen richtig verstehe).
DavidC
1
@DavidCarraher: Annahmen: Die Zeichenfolge besteht nur aus Zahlen. Wenn die Zeichenfolge Buchstaben enthält, können Sie nicht definiertes Verhalten haben Ich denke , dass „nicht definiertes Verhalten“ bedeutet , dass es könnte 2 ausspucken oder es könnte Brei ausspucken
Kyle Kanos
Kyle, sehr gute Beobachtung!
DavidC
1

Scala (83 Zeichen)

Ich war mir nicht sicher, wie ich Eingaben für das Programm bereitstellen sollte, daher dachte ich, dass dies ndie Eingabe ist. Hier ist die tatsächliche Lösung (basierend auf der die Lösungslänge bewertet wird). Darunter befindet sich eine ausführbare Form der Lösung (die noch nicht gespielt ist) zur Ausführung zusammen mit der Ausgabe (für die Beispiele gibt OP an).

Lösung:

n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max

Ausführbare Lösung:

object A {
  def main(x:Array[String])=List("3571","123","23","1236503","46462","4684","460","4601","12 monkeys..").foreach(e=>println(e+" => "+q(e)))

  private def p(n: String)=n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max
  private def q(n: String)=try p(n)catch{case e=>e.toString}
}

Beispielausgabe:

3571 => 3571
123 => 23
23 => 23
1236503 => 236503
46462 => 2
4684 => java.lang.UnsupportedOperationException: empty.max
460 => java.lang.UnsupportedOperationException: empty.max
4601 => 601
12 monkeys.. => java.lang.NumberFormatException: For input string: "12 "

Erläuterung:

Die Schritte sind ziemlich einfach.

Eingabe -> Alle Teilzeichenfolgen suchen -> Nicht-Primzahlen filtern -> längsten Wert suchen

  • main(Array[String]): Methode liefert Beispieleingabe und führt Methode q(String)für jede Eingabe aus
  • q(String): Schließt die tatsächliche Programmlogik ab, p(String)sodass alle Ausnahmen angemessen gemeldet werden. Hilft bei der Formatierung der Ausgabe besser, da ungültige Eingaben NumberFormatExceptions bekommen, wo das Fehlen einer Primzahl eineUnsupportedOperationException
  • p(String): Aktuelle Logik des Programms. Teilen wir die Erklärung dafür in Teile auf
    • n.inits: Erstellt eine Iterator, um über die String-Eingabe zu iterieren ( n)
    • flatMap(f): Wendet eine Operation auf die an Iteratorund schiebt das Ergebnis in eineList
      • _.tails.toList.init.map(BigInt(_)): Teilt das Stringund entfernt leere Strings aus dem Ergebnis List. Konvertiert schließlich das Stringin a, BigIntwas einem Äquivalent von entspricht java.math.BigInteger. Aus Golfgründen BigIntwird ausgewählt (kürzerer Name).
    • filter(f): Wenn fzurückgegeben wird false, wird der Wert aus dem Ergebnis entferntList
      • _ isProbablePrime 1: Diese Zeile hätte geschrieben werden können, _.isProbablePrime(1)aber die verwendete Darstellung spart 1 Byte. Diese Zeile prüft tatsächlich, ob der Wert eine Primzahl ist (wahrscheinlich; da gesetzt certaintyist 1, steigt die Ausführungszeit, aber das System stellt (mehr oder weniger) sicher, dass die Zahl eine Primzahl ist.
    • max: Findet den Maximalwert (nicht Stringbasierte Länge. Tatsächlicher Maximalwert)
javatarz
quelle
1

J ( 24 22)

Das Lesen von der Tastatur ist tatsächlich kürzer als das Definieren einer Funktion.

>./(*1&p:);".\.\1!:1[1

Prüfung:

   >./(*1&p:);".\.\1!:1[1
3571
3571
   >./(*1&p:);".\.\1!:1[1
46462
2
   >./(*1&p:);".\.\1!:1[1
1236503
236503
   >./(*1&p:);".\.\1!:1[1
4684
0
   >./(*1&p:);".\.\1!:1[1
4680
0
   >./(*1&p:);".\.\1!:1[1
twelve monkeys is a pretty good movie
__

Erläuterung:

  • 1!:1[1: Lesen Sie eine Textzeile von der Tastatur
  • ".\.\: die Auswertung ( ".) jedes Suffix ( \.) jedes Präfixes ( \) der Zeichenfolge.
  • ;: Reduzieren Sie die Matrix
  • *1&p:: Multiplizieren Sie jeden Wert damit, ob es sich um eine Primzahl handelt oder nicht (alle Nicht-Primzahlen sind also Null).
  • >./: Holen Sie sich den größten Wert in der Liste
Marinus
quelle
1

Haskell, 94

main=getLine>>=print.maximum.filter(\x->and$map((0/=).mod x)[2..x-1]).map read.init.scanr(:)[]

Vektorweg
quelle
3
Möchten Sie den Prozess dahinter für diejenigen erklären, die Haskell nicht machen?
@ LegoStormtroopr Klar, ich versuche es. main = getLine >>= print . maximum . filter isPrime . map read . allNumsist die ursprüngliche Form. es erhält eine Zeile und gibt sie ( >>=) an die große kombinierte Funktion - kombiniert mit dem .Infix-Operator, der einfach das Ergebnis der rechten Funktion in die linke Funktion setzt. Dinge wie (\x -> ...)sind Lambda-Ausdrücke. Funktionsparameter werden ohne Klammern angewendet und Funktionen können teilweise angewendet werden ( (0/=)z. B. eine Funktion, die prüft, ob eine Zahl nicht 0 ist).
Vektorweg
allNums = init . scanr (:) []. scanrscans and init entfernt den letzten Wert des Ergebnisses von scanr, bei dem es sich um eine leere Zeichenfolge handelt, die nicht in eine Ganzzahl gelesen werden kann. map readLiest eine Liste von Zeichenfolgen zu den festgelegten Werten. in diesem Fall Integer oder etwas anderes aus der Integral-Typklasse, da isPrimeein Integral benötigt wird. filter isPrimemacht genau das, was es sagt. isPrime x = and $ map ((0/=). mod x) [2..(x-1)]bedeutet, bei einer Liste von 2 bis (x-1) die Teilungsprüfung durchzuführen und dann andauf die Bool-Liste anzuwenden .
Vektorweg
Es gibt einige klarere und leistungsfähigere Funktionen in anderen Standardmodulen, aber ich habe versucht, nur mit dem Prelude-Modul zu arbeiten. ;)
Vektorweg
1

Perl 6 (40 Zeichen, 41 Bytes)

$_=get;say max grep &is-prime,+«m:ex/.+/

Bei der ersten getEingabe in $_verkürzt sich der Regex-Match-Aufruf. :exgibt erschöpfendes Matching für Regex, es gibt alle Möglichkeiten. Der Hyper-Op (oder +<<funktioniert auch) macht Zahlen aus den Match-Objekten, die grepmit &is-primesub als Selektor übergeben werden. Nehmen Sie zum Schluss das Maximum der verbleibenden Liste und geben Sie es aus.

Ayiko
quelle
0

Mathematica 67 47

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&

Erläuterung

Der Code ist eine reine Funktion. Es hat keinen Namen. Darin #steht die vollständige Eingabezeichenfolge.

StringCasesNimmt die Eingabe # und sucht nach Teilzeichenfolgen aeines oder mehrerer Zeichen (deshalb wurde __ anstelle von _ verwendet), die Primzahlen sind. PrimeQ muss True für den Teilstring zurückgeben.

Alle günstigen Fälle, dh die Teilzeichenfolgen, die Primzahlen sind, werden standardmäßig in einer Liste zurückgegeben. 〚1〛oder [[1]]nimmt den ersten Teil, dh das erste Element dieser Liste von Primzahlen. element[[1]]ist eine Abkürzung für Part[element, 1]. Wenn es mehr als eine Primzahl gibt, ist die erste die längste Primzahl ( StringCasesüberprüft zuerst die längsten Teilzeichenfolgen).

Beispiele

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&["1236503"]

236503

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&/@ 
{"1236503", "123", "46462", "4684", "460", "4601", 
"12 monkeys is a pretty good movie, but not as good as se7en"}

{236503, 23, 2, {} [[1]], {} [[1]], 601, 2}

DavidC
quelle
Möchten Sie den Prozess dahinter für diejenigen erklären, die Mathematica nicht machen?
1
Ich muss sagen, dass die Verwendung von 〚1〛Zeichen für uns Nicht-Mathematiker-Programmierer sadistisch war. (Cue mich verzweifelt besorgt, dass ich blind werde, und dann andere Klammern mit der Verwirrung betrachten, dass sie scharf aussehen, während dies nicht ist!)
eithed
〚1〛hat doppelte Klammern und entspricht [[1]]. Ich habe sie verwendet, weil eine doppelte Klammer als einzelnes Zeichen zählt.
DavidC
@ David Carraher Ja, aber ich denke, du musst es als zwei Bytes zählen, damit es dir nichts wirklich erspart.
Michael Stern
Aber ich zähle Zeichen, keine Bytes. Bitte erkläre.
DavidC
0

Perl 6 (50 Zeichen, 51 Bytes)

say max +«get.match(/(.+)<?{(+$0).is-prime}>/,:ex)

Ordnet Zeichenfolgen Zahlen zu, maxerhält die größte Zahl und geterhält eine Zeile./(.+)<?{(+$0).is-prime}>/ist ein regulärer Ausdruck, der alle Primzahlen erhält, <?{}>ist eine Code-Behauptung. is-primeist eine IntKlassenmethode, die prüft, ob die Zahl eine Primzahl ist. Ich muss den Wert mithilfe von in Zahl umwandeln +, da dies Strstandardmäßig der Fall ist. :exbedeutet, dass versucht wird, ALLE Übereinstimmungen zu finden (einschließlich solcher, bei denen sich andere überschneiden). Aufgrund des Rakudo Perl-Fehlers ist eine Verwendung m//hier derzeit nicht möglich .

Dies funktioniert für jede Nummer und wenn Sie sie entfernen max(oder durch ersetzen)sort andere ), erhalten Sie eine Liste aller Primzahlen in der Zahl, um einen zusätzlichen Bonus zu erhalten (nicht, dass dies Punkte oder irgendetwas gibt). Zum Beispiel (mit sortin diesem Fall):

1234567890
2 3 5 7 23 67 89 4567 23456789
Konrad Borowski
quelle