Détectez le langage de programmation d'un extrait


23

Votre défi est de prendre du code source en entrée et de sortir dans quel langage de programmation il est écrit.

Par exemple, vous pourriez avoir l'entrée

class A{public static void main(String[]a){System.out.println("Hello, World!");}}

Et sortie

Java

Vos deux objectifs principaux sont la diversité (combien de langages de programmation vous pouvez détecter) et la précision ( votre capacité à détecter ces langages).

Pour les polyglottes (programmes valables dans plusieurs langues), vous pouvez décider quoi faire. Vous pouvez simplement générer le langage que votre programme pense être le plus probable, ou vous pouvez générer une erreur, ou vous pouvez générer un tableau de choix possibles (ce qui entraînerait probablement plus de votes positifs qu'une simple erreur!).

Il s'agit d'un , car il serait très difficile de spécifier un critère de gain objectif différent. Électeurs, veuillez voter sur le nombre de langues qu'il peut détecter et sa précision.


C'est impossible, car il print("")peut être utilisé dans de nombreuses langues.
Ismael Miguel

1
Avec votre montage, cela semble désormais plus possible.
Ismael Miguel

4
Qu'en est-il des langues valables pour CHAQUE entrée? Comme un espace. Cette phrase est un programme d'espaces valide. Cette page entière est un programme d'espaces valide.
Ismael Miguel

1
L'entrée est-elle garantie comme un programme valide? Comme une entrée pourrait être class A{public static void main(String[]a){System.println.out("Hello, World!");}}invalide.
Gaurang Tandon

1
Ou de même, l'entrée HTML commencera-t-elle toujours par <!DOCTYPE html>suivie des balises <html>, <body>et autres (comme meta) dans leur ordre correct?
Gaurang Tandon

Réponses:


18

234 formats de texte - Unix Shell

(pas toutes les langues - je dois les compter soigneusement)

file $1

J'hésite à publier cette réponse quelque peu intelligente, mais je ne vois rien dans les règles qui l'interdisent et l' fileutilitaire shell fait vraiment du bon travail. par exemple:

$ file golfscript.rb 
golfscript.rb: Ruby module source, ASCII text
$ file template.c 
template.c: ASCII C program text
$ file adams.sh
adams.sh: Bourne-Again shell script, ASCII text executable
$ 

De plus, vous pouvez utiliser l' -koption pour "continuer" lors du test d'un polyglotte:

 -k, --keep-going
         Don't stop at the first match, keep going.  Subsequent matches
         will be have the string ‘\012- ’ prepended.  (If you want a new‐
         line, see the -r option.)

En outre, l' -loption vous donnera une idée de la qualité de l'algorithme pour différentes langues:

$ file -l | coquille de grep
inconnu, 0: avertissement: utilisation du fichier magique normal `/ etc / magic '
Strength = 280: shell archive text [application / octet-stream]
Force = 250: exécutable texte du script shell Tenex C [text / x-shellscript]
Strength = 250: Bourne-Again shell script text executable [text / x-shellscript]
Strength = 240: l'exécutable de texte du script zsh de Paul Falstad [text / x-shellscript]
Strength = 240: exécutable texte de script de cendre de Neil Brown [text / x-shellscript]
Strength = 230: l'exécutable de texte de script ae de Neil Brown [text / x-shellscript]
Strength = 210: exécutable texte du script shell Tenex C [text / x-shellscript]
Strength = 210: Bourne-Again shell script text executable [text / x-shellscript]
Force = 190: exécutable texte du script shell Tenex C [text / x-shellscript]
Strength = 190: Bourne-Again shell script text executable [text / x-shellscript]
Strength = 180: l'exécutable de texte du script zsh de Paul Falstad [text / x-shellscript]
Force = 150: exécutable texte du script shell Tenex C [text / x-shellscript]
Strength = 150: Bourne-Again shell script text executable [text / x-shellscript]
Strength = 140: C shell script text executable [text / x-shellscript]
Strength = 140: Korn shell script text executable [text / x-shellscript]
Strength = 140: l'exécutable de texte du script zsh de Paul Falstad [text / x-shellscript]
Strength = 130: POSIX shell script text executable [text / x-shellscript]
Strength = 130: Plan 9 rc shell script text executable []
$ 

C'est file-5.09(sur Ubuntu 12.04)


Cela fonctionne plutôt bien sur un polyglotte en 16 langues - gist.github.com/riking/9088817
Riking

Vous pourriez aussi bien découper l'homme du milieu et éviter la coquille entièrement: ln -s /usr/bin/file /usr/local/bin/myspecialtool. Si votre réponse compte, cela ne compte-t-il pas aussi bien? (Ne vous inquiétez pas, je ne suis pas sérieux.)
hvd

2
Ressemble à une faille standard, c.-à-d. Déléguer la solution au programme existant.
Vi.

10

Bash - à propos 50 35 octets par langue compilable

L'astuce consiste à simplement compiler, alors vous n'avez pas à vous soucier de lier les erreurs des bibliothèques manquantes, et c'est plus indulgent si vous n'avez que des extraits de code.

Merci à Shahbaz pour les formes plus courtes!

gcc -c $1 && (echo C; exit 0)
g++ -c $1 && (echo C++; exit 0)
gpc -c $1 && (echo Pascal; exit 0)
gfortran -c $1 && (echo Fortran; exit 0)

etc...


Puisque vous mentionnez le nombre d'octets par langue compilable, vous pourriez être intéressé par des lignes comme:gcc -c $1 && (echo C; exit 0)
Shahbaz

Merci, je ne suis pas très bon pour serrer vraiment le code!

Sûr. Le &&et ||dans bash sont vraiment utiles et aident beaucoup à nettoyer le code. Ils ne sont en aucun cas utilisés pour l'obscurcissement, vous feriez donc bien de les apprendre.
Shahbaz

2
Vous pouvez également passer -fsyntax-onlypour vérifier uniquement la syntaxe et ignorer la compilation réelle.
peppe

7

18 langages de programmation, 1002 octets, précision: testez par vous-même :)

(ouais je sais que ce n'est pas du golf de code, mais pour le plaisir)

Le programme recherche des extraits de code emblématiques, les vérifications sont ordonnées de manière à ce que les vérifications les plus claires soient en haut et les langages de programmation intégrés dans d'autres langages de programmation sont en dessous (par exemple HTML en PHP).

Cela échoue évidemment pour des programmes comme System.out.println('<?php');

t = (p) ->
    h = (x) -> -1 != p.indexOf x
    s = (x) -> 0 == p.indexOf x

    if h "⍵" then "APL"
    else if h "<?php" then "PHP"
    else if h("<?xml") and h "<html" then "XHTML"
    else if h "<html" then "HTML"
    else if h "<?xml" then "XML"
    else if h("jQuery") or h "document.get" then "JavaScript"
    else if h "def __init__(self" then "Python"
    else if h "\\documentclass" then "TeX"
    else if h("java.") or h "public class" then "Java"
    else if s("SELE") or s("UPDATE") or s "DELE" then "SQL"
    else if /[-\+\.,\[\]\>\<]{9}/.test p then "Brainfuck"
    else if h "NSString" then "Objective-C"
    else if h "do |" then "Ruby"
    else if h("prototype") or h "$(" then "JavaScript"
    else if h "(defun" then "Common Lisp"
    else if /::\s*[a-z]+\s*->/i.test p then "Haskell"
    else if h "using System" then "C#"
    else if h "#include"
        if h("iostream") or h "using namespace" then "C++"
        else "C"
    else "???"

program = ""
process.stdin.on 'data', (chunk) -> program += chunk
process.stdin.on 'end', -> console.log t program

Utilisation sur le nœud: coffee timwolla.coffee < Example.java

Démo (Démo en ligne sur JSFiddle ):

[timwolla@~/workspace/js]coffee puzzle.coffee < ../c/nginx/src/core/nginx.c 
C
[timwolla@~/workspace/js]coffee puzzle.coffee < ../ruby/github-services/lib/service.rb
Ruby
[timwolla@~/workspace/js]coffee puzzle.coffee < ../python/seafile/python/seaserv/api.py
Python

Sur mon ordinateur, cela ne produit rien, pas même sur une entrée qui devrait évidemment fonctionner. Certes, je fais peut-être quelque chose de mal car je n'ai jamais utilisé Coffeescript auparavant.
marinus

@marinus Notez que lors de la saisie manuelle de code, vous devez envoyer un EOF (STRG + D) pour déclencher l'exécution. Généralement: le détecteur doit au moins cracher trois points d'interrogation.
TimWolla

Non, rien. Dois-je transmettre coffeedes arguments? Je venais juste d'essayer de rediriger des fichiers vers celui-ci, mais simplement l'exécuter et aller ^Dne fait rien non plus.
marinus

@marinus Try: npm install coffee-script && node_modules/.bin/coffee timwolla.coffee < timwolla.coffeedans un dossier temporaire, cela devrait cracher APL. (en supposant que vous avez une version récente du nœud et de npm installés)
TimWolla

5
Je vais commencer à utiliser plus d'oméga en minuscules dans mes programmes non APL.
John Dvorak

4

Cette réponse est une preuve de concept, qui ne recevra probablement plus de travail de ma part.

Il échoue de plusieurs manières:

  • La sortie n'est pas exactement comme le demande la question, mais assez proche et pourrait facilement être modifiée pour produire la sortie exacte requise.
  • Il existe plusieurs façons de rendre le code plus performant et / ou de mieux représenter les structures de données.
  • et plus

L'idée est de définir une liste de mots-clés / caractères / phrases qui peuvent identifier une langue spécifique et attribuer un score à ce mot-clé pour chaque langue. Vérifiez ensuite le (s) fichier (s) source (s) pour ces mots clés et faites le pointage des scores pour chaque langue pour laquelle vous trouvez des mots clés. En fin de compte, la langue avec le score le plus élevé est le gagnant probable. Cela s'adresse également aux programmes polyglottes, car les deux (ou toutes) les langues pertinentes obtiendront un score élevé.

La seule chose pour ajouter plus de langues est d'identifier leurs "signatures" et de les ajouter au mappage.

Vous pouvez également attribuer différents scores à différents mots clés par langue. Par exemple, si vous pensez qu'il volatileest plus utilisé en Java qu'en C, définissez le score du volatilemot-clé sur 2 pour Java et 1 pour C.

public class SourceTest {

  public static void main(String[] args) {
    if (args.length < 1) {
      System.out.println("No file provided.");
      System.exit(0);
    }
    SourceTest sourceTest = new SourceTest();
    for (String fileName : args) {
      try {
        sourceTest.checkFile(fileName);
      } catch (FileNotFoundException e) {
        System.out.println(fileName + " : not found.");
      } catch (IOException e) {
        System.out.println(fileName + " : could not read");
      }
    }
    System.exit(0);
  }

  private Map<String, LanguagePoints> keyWordPoints;
  private Map<LANGUAGES, Integer> scores;

  private enum LANGUAGES {
    C, HTML, JAVA;
  }

  public SourceTest() {
    init();
  }

  public void checkFile(String fileName) throws FileNotFoundException, IOException {
    String fileContent = getFileContent(fileName);
    testFile(fileContent);
    printResults(fileName);
  }

  private void printResults(String fileName) {
    System.out.println(fileName);
    for (LANGUAGES lang : scores.keySet()) {
      System.out.println("\t" + lang + "\t" + scores.get(lang));
    }
  }

  private void testFile(String fileContent) {
    for (String key : keyWordPoints.keySet()) {
      if (fileContent.indexOf(key) != -1) {
        for (LANGUAGES lang : keyWordPoints.get(key).keySet()) {
          scores.put(lang, scores.get(lang) == null ? new Integer(1) : scores.get(lang) + 1);
        }
      }
    }
  }

  private String getFileContent(String fileName) throws FileNotFoundException, IOException {
    File file = new File(fileName);
    FileReader fr = new FileReader(file);// Using 1.6 so no Files
    BufferedReader br = new BufferedReader(fr);
    StringBuilder fileContent = new StringBuilder();
    String line = br.readLine();
    while (line != null) {
      fileContent.append(line);
      line = br.readLine();
    }
    return fileContent.toString();
  }

  private void init() {
    scores = new HashMap<LANGUAGES, Integer>();

    keyWordPoints = new HashMap<String, LanguagePoints>();
    keyWordPoints.put("public class", new LanguagePoints().add(LANGUAGES.JAVA, 1));
    keyWordPoints.put("public static void main", new LanguagePoints().add(LANGUAGES.JAVA, 1));
    keyWordPoints.put("<html", new LanguagePoints().add(LANGUAGES.HTML, 1));
    keyWordPoints.put("<body", new LanguagePoints().add(LANGUAGES.HTML, 1));
    keyWordPoints.put("cout", new LanguagePoints().add(LANGUAGES.C, 1));
    keyWordPoints.put("#include", new LanguagePoints().add(LANGUAGES.C, 1));
    keyWordPoints.put("volatile", new LanguagePoints().add(LANGUAGES.JAVA, 1).add(LANGUAGES.C, 1));
  }

  private class LanguagePoints extends HashMap<LANGUAGES, Integer> {
    public LanguagePoints add(LANGUAGES l, Integer i) {
      this.put(l, i);
      return this;
    }
  }
}

4

Juste quelques grandes généralisations.

Je pense que c'est assez précis.

Voici Ruby btw. Prend l'entrée (multiligne) de stdin.

puts case $<.read
when /\)\)\)\)\)/
  "Lisp"
when /}\s+}\s+}\s+}/
  "Java"
when /<>/
  "Perl"
when /|\w+|/
  "Ruby"
when /\w+ :- \w+ \./
  "Prolog"
when /^[+-<>\[\],.]+$/
  "brainfuck"
when /\[\[.*\]\]/
  "Bash"
when /~]\.{,/
  "golfscript"
end

Je pense que #include est un meilleur prédicteur pour c. Qu'en est-il de #! / Bin / (ba)? Sh pour les scripts bash / shell?
Digital Trauma

@DigitalTrauma Oui, je pense que vous avez raison sur #include. Pour des raisons artistiques, je ne vais pas juste attraper le hash-bang où le nom de la langue est explicitement énoncé.
daniero

#include est un commentaire dans les inifichiers etphp
Ismael Miguel

1
+1 pour avoir prologue, mais pas de C :)
SztupY

1
J'ajouterais \$\w+après le perl pour détecter PHP. Est également (\w+)::~\1généralement un destructeur C ++
SztupY

2

Javascript - 6 langues - haute précision

Langues actuelles: Java, C, HTML, PHP, CSS, Javascript

Je travaille sur le principe que chaque fois qu'une entrée satisfait à un critère, elle reçoit un score, et sur la base de ce score, les résultats sont donnés.

Fonctionnalités:

  • Aucune fonction intégrée qui détermine le type de langage utilisé.
  • Ne déclare pas immédiatement que le texte saisi est une xlangue en voyant un mot-clé.
  • Suggère également d'autres langues probables.

Si vous pensez que vos entrées des programmes (que j'ai faites jusqu'à présent) ne sont pas prises ou n'obtiennent pas de résultats invalides, veuillez le signaler et je serais heureux de les corriger.

Exemple d'entrée 1:

class A{public static void main(String[]a){System.out.println("<?php");}}

Exemple de sortie 1:

My program thinks you have :
Java with a chance of 100%
Php with a chance of 25%
----------------

Explication:

Cela aurait dû faire échouer le programme et j'aurais imprimé PHP, mais comme mon programme fonctionne sur la base des scores, rien n'échoue et il identifie facilement Java en premier lieu, suivi d'autres résultats possibles.

Exemple d'entrée 2:

class A{public static void main(String[]a){System.out.println("HelloWorld!");}}

Exemple de sortie 2:

Java
----------------

Exemple d'entrée 3:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

Exemple de sortie 3:

Language not catched! Sorry.
----------------

Le code:

// Helper functions

String.prototype.m = function(condition){
  return this.match(condition);
};

String.prototype.capitalize = function(){
  return this[0].toUpperCase() + this.substr(1);
};

function getFuncName(func){
  var temp =  func.toString();
  temp = temp.substr( "function ".length);
  temp = temp.substr( 0, temp.indexOf("("));
  return temp.capitalize();
}

// Get input
var lang_input = prompt("Enter programming language");

// Max score of 4 per lang

function java(input){
  var score = 0;
  score += input.m(/class[\s\n]+[\w$]+[\s\n]*\{/) ? 1 : 0;
  score += input.m(/public[\s\n]+static[\s\n]+void[\s\n]+main[\s\n]*/) ? 1 : 0;
  score += input.m(/\}[\s\n]*\}[\s\n]*$/) ? 1 : 0;
  score += input.m(/System[\s\n]*[.][\s\n]*out/) ? 1 : 0;
  return score;
}

function c(input){
  var score = 0;
  // if java has passsed
  if(checks[0][1] >= 3)return 0;

  score += input.m(/^#include\s+<[\w.]+>\s*\n/) ? 1 : 0;
  score += input.m(/main[\s\n]*\([\s\n]*(void)?[\s\n]*\)[\s\n]*\{/) ? 1 : 0;
  score += input.m(/printf[\s\n]+\(/) || input.m(/%d/) ? 1 : 0;
  score += input.m(/#include\s+<[\w.]+>\s*\n/) || input.m(/(%c|%f|%s)/) ? 1 : 0;
  return score;
}

function PHP(input){
  var score = 0;
  score += input.m(/<\?php/) ? 1 : 0;
  score += input.m(/\?>/) ? 1 : 0;
  score += input.m(/echo/) ? 1 : 0;
  score += input.m(/$[\w]+\s*=\s*/) ? 1 : 0;
  return score;
}

function HTML(input){
  var score = 0;
  // if php has passed
  if(checks[2][1] >= 2) return 0;

  score += input.m(/<!DOCTYPE ["' \w:\/\/]*>/) ? 1 : 0;
  score += input.m(/<html>/) && input.m(/<\/html>/) ? 1 : 0;
  score += input.m(/<body>/) && input.m(/<\/body/) ? 1 :  0;
  score += input.m(/<head>/) && input.m(/<\/head>/) ? 1 : 0;
  return score;
}

function javascript(input){
  var score = 0;
  score += input.m(/console[\s\n]*[.][\s\n]*log[\s\n*]\(/) ? 1 : 0;
  score += input.m(/[\s\n]*var[\s\n]+/) ? 1 : 0;
  score += input.m(/[\s\n]*function[\s\n]+[\w]+[\s\n]+\(/) ? 1 : 0;
  score += input.m(/document[\s\n]*[.]/) || 
           ( input.m(/\/\*/) && input.m(/\*\//) ) ||
           ( input.m(/\/\/.*\n/) )? 1 : 0;
  return score;
}

function CSS(input){
  var score = 0;
  score += input.m(/[a-zA-Z]+[\s\n]*\{[\w\n]*[a-zA-Z\-]+[\s\n]*:/) ? 1 : 0;
  // since color is more common, I give it a separate place
  score += input.m(/color/) ? 1 : 0;          
  score += input.m(/height/) || input.m(/width/) ? 1 : 0;
  score += input.m(/#[a-zA-Z]+[\s\n]*\{[\w\n]*[a-zA-Z\-]+[\s\n]*:/) ||
           input.m(/[.][a-zA-Z]+[\s\n]*\{[\w\n]*[a-zA-Z\-]+[\s\n]*:/) ||
           ( input.m(/\/\*/) && input.m(/\*\//) ) ? 1 : 0;
  return score;
}

// [Langs to check, scores]
var checks = [[java, 0], [c, 0], [PHP, 0], [HTML, 0], [javascript, 0], [CSS, 0]];
//Their scores

// Assign scores
for(var i = 0; i < checks.length; i++){
  var func = checks[i][0];
  checks[i][1] = func(lang_input);
}

// Sort the scores
checks.sort(function(a,b){ return b[1] - a[1]; });

var all_zero = true;

function check_all_zero(index){
  if(checks[index][1] > 0){ all_zero = false; return 0; } // someone is above zero

  // check next index only if it defined, else return zero
  if(checks[index + 1])
    check_all_zero(index + 1);
}

check_all_zero(0);

if(all_zero){
  console.log("Language not catched! Sorry.");
}else {
  var new_arr = [];                   // temp

  checks.map(function(value, index){
    if(value[1] > 0){
      var temp = [getFuncName(value[0]), value[1]];
      new_arr.push(temp);
    }
  });

  checks = new_arr.slice(0);          // array copy, because of mutation

  if(checks.length === 1){
    console.log(checks[0][0]);
  }else{
    console.log("My program thinks you have :");
    checks.map(function(value){
      var prob = (value[1]/4 * 100);
      console.log(value[0] + " with a chance of " + prob + "%");
    });
  }

} // Main else block finish

console.log("----------------");
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.