Est-ce un premier choix? sans mathématiques [fermé]

14

Écrivez un programme ou une fonction dans n'importe quelle langue qui indique si l'entrée est un nombre premier.

  • L'entrée est une chaîne représentant un nombre naturel en base-10.
  • La sortie est l'une des deux chaînes "Prime" ou "Not !!" qui identifie correctement l'entrée.
  • Les opérateurs arithmétiques, les opérateurs bit à bit, les variables et constantes numériques, les "math-stuff" en général, etc ... ne sont autorisés nulle part dans votre programme. Vous devez utiliser des opérations de chaîne pour effectuer tous les "calculs" nécessaires.
  • Vous pouvez comparer les longueurs de chaîne (qui sont des nombres) - mais -10 à votre score si vous ne le faites pas.
  • Votre programme devrait fonctionner sur n'importe quelle entrée de longueur (avec suffisamment de mémoire et de temps).
  • Le nombre d'octets le plus bas (UTF-8) l'emporte.
Wally
la source
Quelles sont les limites du nombre? Peut-il être négatif? Zéro? Peut-il contenir un point décimal?
Justin
S'il a des points bonus, ce n'est pas du golf de code
Peter Taylor
Ajout de "naturel" pour spécifier les limites de l'entrée.
Wally le
J'espérais être surpris par une folle manipulation de chaîne explicite (je pensais personnellement à écrire du code pour "décrémenter" une chaîne afin de pouvoir boucler - et j'étais déchiré entre la division longue de la chaîne et la soustraction répétée de la chaîne ...), au lieu de cela, je a été surpris par ce petit matcher principal unaire regex cool! Peut-être que je dois poser la question à nouveau en interdisant l'expression régulière pour voir si j'obtiens des choses encore plus merveilleuses? Mais je ne pense pas que quoi que ce soit puisse se rapprocher de la brièveté de cette expression régulière.
Wally
Pour obtenir "plus de trucs merveilleux", vous pourriez peut-être essayer d'en faire un concours de popularité . Changer la question elle-même est généralement mal vu. Et je ne suis pas sûr que vous devriez poser une nouvelle question ou changer quoi que ce soit juste parce que quelqu'un a proposé quelque chose auquel vous n'avez pas pensé - je pense que cela arrive assez souvent ici. De plus, le pliage des règles fait partie du sport :)
daniero

Réponses:

7

Rubis, 64-10 = 54

puts ('1
'..gets).map{?1}*''=~/^1?$|^(11+?)\1+$/?'Not!!': :Prime

Cela itère de la chaîne '1' (plus une nouvelle ligne) à la chaîne d'entrée, en utilisant la méthode d'itération de chaîne intégrée de Ruby qui ressemble énormément à l'ajout de 1, mais qui ne crée techniquement aucune variable numérique de haut niveau à aucun moment . Il utilise le fait qu'il y aura n itérations pour une entrée de n pour créer une chaîne de longueur n, puis utilise une expression régulière pour déterminer si cette chaîne peut être regroupée en sous-chaînes identiques.

histocrate
la source
Le "1" dans la "carte {? 1}" est-il un Fixnum? - si c'est le cas, vous devrez peut-être le remplacer par "map ('1')? Je ne trouve aucune documentation sur l'expression? 1, à l'exception de certains indices selon lesquels dans les anciennes versions de Ruby, il renvoyait des codes ASCII et maintenant, il renvoie une chaîne .
Wally le
? 1 est identique à «1», c'est un littéral de chaîne à 1 caractère. Je pourrais remplacer toutes les instances de 1, mais la première par tout autre caractère.
histocrate
Ok - je ne pouvais pas trouver cette construction bien décrite nulle part!
Wally
Je choisis cela comme "le gagnant" car cela fait tout pour éviter même un soupçon de mathématiques.
Wally
3
Pas de pointe de chapeau pour Abigail? Par honte. Ceci est un port direct de la solution Perl 1998: catonmat.net/blog/perl-regex-that-matches-prime-numbers
skibrianski
16

Rubis: 52-10 = 42

En utilisant une variation de cette fameuse expression rationnelle d'appariement premier.

puts ?_*gets.to_i=~/^(_|(__+?)\2+)$/?"Not!!":"Prime"

Juste pour être clair: ?_*gets.to_iest une opération de chaîne qui s'ajoute "_"à elle-même n fois, où n est le numéro d'entrée. Comme je le vois, aucune longueur de chaîne n'est comparée, ce qui devrait satisfaire au critère de bonus de 10 caractères.

daniero
la source
1
Je ne connais pas très bien Ruby, corrigez-moi si je me trompe, mais le "to_i" ne convertit-il pas la chaîne en entier? Non pas que je n'aime pas le vérificateur principal brillant dans unaire…
Wally
1
@Wally Je ne pense pas que "convertir" ne soit pas le bon mot, mais la méthode renvoie un entier, oui. Pourtant, je n'utilise aucun des éléments suivants Arithmetic operators, bit-wise operators, numeric variables and constants, et vous ne pouvez pas vraiment classer l'appel d'une méthode comme "math-stuff" in general..?
daniero
@daniero Cela semble raisonnable - peut-être juste au bord de la spécification.
Wally
3

Perl 52-10 = 42

la mise en oeuvre

print((('-'x$ARGV[0])=~/^.$|^(..+?)\1+$/)?Not:Prime)

Démo

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && perl Prime.pl {} && echo"
1 Not
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
la source
4
1 n'est pas vraiment une prime.
elixenide
Utilise un index de tableau numérique - donc au bord de la spécification.
Wally
Utilisez à la popplace de $ARGV[0], enregistrez 4 caractères, supprimez l'index du tableau numérique
mob
1

ECMAScript 6, 159 - 10 = 149

Sonne comme une tâche pour regex. E / S avec prompt/ alertcomme d'habitude.

for(s=prompt(u=""); /[^0]/.test(s); )
  s=s.replace(/(.)(0*)$/,(_,d,t)=>u+="x"," 012345678"[d]+t.replace(/0/g,"9"))
alert(/^((xx+)\2+|x?)$/.test(u)?"Not!!":"Prime")

La boucle while décrémente le nombre décimal d'une unité à chaque itération uniquement par l'expression régulière. Le regex final correspond à une chaîne composée d'un nombre composé de x, en faisant d'abord correspondre un facteur, puis un autre en répétant le premier facteur un pour le reste de la chaîne.

Luciole
la source
J'aime la fonction de décrémentation de chaîne - claire et concise.
Wally
1

Javascript 266

function N(a){function b(a){return P.every(function(b){if(n=b,i=a.length,j=b.length,j>i) return;if(j==i) return 1;while(n.length<i)n+=b;return n.length!=i})}if(q=A,A!=a)for(;q.length.toString()!=a;)b(q)&&P.push(q),q+=A;console.log(b(q)?"Prime":"Not!!")}A="0",P=[A+A]

Crée une fonction appelée N qui imprimera le résultat souhaité. La version non réduite ressemble à ceci. J'ai fait une minification de la main pour nettoyer certaines variables, puis j'ai exécuté cela à travers uglify, puis à nouveau minifié à la main.

// A a string of "0" for using to generate long strings
// P is the store for all known primes
A="0", P=[A+A];
function N(val) {
  function _isPrime(str) {
    // go through all the known primes and return true
    // if we don't match on any of them
    return P.every(function(prime) {
      // prime is some known string whose length is a prime number
      tsr = prime, strlen = str.length, primelen = prime.length;
      // if the string we're checking has fewer chars than
      // this then it's not a prime
      if(strlen < primelen) return 0;
      // if the string we're checking has the same number of chars
      // as the the prime we're checking against then it is a prime
      if(primelen == strlen) return 1;
      // Keep incrementing our temporary string with the prime we're
      // checking. we'll break out of the loop once the temporary string
      // is greater than or equal to the string we're testing
      while(tsr.length < strlen) {
        tsr += prime;
      }
      return !(tsr.length == strlen)
    });
  }
  // start with a string of one unit
  nstr = A
  if(A!=val) {
    // keep incrementing the string so that we can compile a list
    // of known primes smaller than this value
    while(nstr.length.toString() !== val) {
      if(_isPrime(nstr)) {
        P.push(nstr);
      }
      nstr += A;
    }
  }
  console.log(_isPrime(nstr) ? "Prime" : "Not!!");
}

Testé à l'aide de cet extrait:

for(var X=0;X<10;X++) {
  console.log('checking: ' + X);
  N(X.toString());
}
Sugendran
la source
1
Je ne suis pas sûr de voir comment cela fonctionne, mais je vois une variable numérique (i) et un opérateur arithmétique (i ++).
Wally
Oh, je ne savais pas que je ne pouvais pas faire une boucle for comme ça .. je vais la réécrire ce soir.
Sugendran
Fondamentalement, je produis un tableau de chaînes dont les longueurs sont des nombres premiers. Ainsi, lorsque j'obtiens une entrée, je continue d'ajouter des caractères à une chaîne jusqu'à ce que la valeur de longueur de la chaîne corresponde à l'entrée. Je prends ensuite cette chaîne et vois si je peux la diviser également par l'un des nombres premiers connus. Si je ne peux pas, ce doit être une prime. Et par division, je veux dire que je prends la chaîne principale connue et que je continue de l'ajouter à elle-même, la longueur de la chaîne est soit égale ou supérieure à la chaîne en question.
Sugendran
J'ai mis à jour le code, cela réduit en fait légèrement le nombre de caractères :)
Sugendran
Cool. Il ressemble à la même idée que l'expression rationnelle, mais plus efficace et montrant explicitement la logique réelle.
Wally
0

Bash 66 - 10 = 56

la mise en oeuvre

[[ -z `printf %$1s|grep -P "^(..+?)\1+$"` ]]&&echo Prime||echo Not

Démo

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && ./Prime.sh {}"
1 Prime
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
la source
Comme ci-dessus, 1 n'est pas premier.
Wally