Detecta qué lenguaje de programación es un fragmento

23

Su desafío es tomar algún código fuente como entrada y salida en qué lenguaje de programación está escrito.

Por ejemplo, podría tener la entrada

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

Y salida

Java

Sus dos objetivos principales son la diversidad (cuántos lenguajes de programación puede detectar) y la precisión (qué tan bueno es para detectar estos lenguajes).

Para los políglotas (programas válidos en más de un idioma), puede decidir qué hacer. Simplemente podría generar el lenguaje que su programa cree que es más probable, o podría generar un error, o podría generar una variedad de posibles opciones (¡lo que probablemente obtendría más votos positivos que solo un error!).

Este es un , porque sería muy difícil especificar un criterio objetivo diferente para ganar. Votantes, voten cuántos idiomas puede detectar y qué tan exactos son.

Pomo de la puerta
fuente
Eso es imposible, porque print("")puede usarse en muchos idiomas.
Ismael Miguel
1
Con tu edición, ahora parece más posible.
Ismael Miguel
44
¿Qué pasa con los idiomas que son válidos para CADA entrada? Como el espacio en blanco. Esta oración es un programa válido de espacios en blanco. Toda esta página es un programa válido de espacios en blanco.
Ismael Miguel
1
¿Se garantiza que la entrada sea un programa válido? Al igual que alguna entrada podría ser class A{public static void main(String[]a){System.println.out("Hello, World!");}}que no es válida.
Gaurang Tandon
1
O así mismo será de entrada HTML siempre comenzar con <!DOCTYPE html>seguido por el <html>, <body>y otras etiquetas (como meta) en su orden correcto?
Gaurang Tandon

Respuestas:

18

234 formatos de texto - Unix Shell

(no todos son idiomas, necesito contarlos cuidadosamente)

file $1

Dudo en publicar esta respuesta algo inteligente, una $$, pero no veo nada en las reglas que lo prohíben y la fileutilidad de shell realmente hace un buen trabajo al respecto. p.ej:

$ 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
$ 

Además, puede usar la -kopción para "continuar" cuando pruebe un políglota:

 -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.)

Además, la -lopción le dará una idea de qué tan bueno es el algoritmo para diferentes idiomas:

$ archivo -l | grep shell
desconocido, 0: Advertencia: uso del archivo mágico regular `/ etc / magic '
Fuerza = 280: texto de archivo de shell [application / octet-stream]
Fuerza = 250: ejecutable del texto del script de shell Tenex C [text / x-shellscript]
Fuerza = 250: ejecutable de texto de script de shell Bourne-Again [text / x-shellscript]
Fuerza = 240: ejecutable del texto del script zsh de Paul Falstad [text / x-shellscript]
Fuerza = 240: ejecutable de texto de script de ceniza de Neil Brown [text / x-shellscript]
Fuerza = 230: ejecutable del texto del script ae de Neil Brown [text / x-shellscript]
Fuerza = 210: ejecutable del texto del script de shell Tenex C [text / x-shellscript]
Fuerza = 210: ejecutable del texto del script de shell Bourne-Again [text / x-shellscript]
Fuerza = 190: ejecutable del texto del script de shell Tenex C [text / x-shellscript]
Fuerza = 190: ejecutable del texto del script de shell Bourne-Again [text / x-shellscript]
Fuerza = 180: ejecutable del texto del script zsh de Paul Falstad [text / x-shellscript]
Fuerza = 150: ejecutable del texto del script de shell Tenex C [text / x-shellscript]
Fuerza = 150: ejecutable del texto del script de shell Bourne-Again [text / x-shellscript]
Fuerza = 140: ejecutable del texto del script de shell C [text / x-shellscript]
Fuerza = 140: ejecutable del texto del script de shell Korn [text / x-shellscript]
Fuerza = 140: ejecutable del texto del script zsh de Paul Falstad [text / x-shellscript]
Fuerza = 130: ejecutable del texto de script de shell POSIX [text / x-shellscript]
Fuerza = 130: ejecutable del texto del script de shell de Plan 9 rc []
PS 

Esto es file-5.09(en Ubuntu 12.04)

Trauma digital
fuente
Esto realmente funciona bastante bien en un políglota de 16 idiomas - gist.github.com/riking/9088817
Riking
Es lo mismo que cortar al hombre medio y evitar la cáscara del todo: ln -s /usr/bin/file /usr/local/bin/myspecialtool. Si su respuesta cuenta, ¿no cuenta esto también? (No te preocupes, no hablo en serio.)
hvd
2
Parece una escapatoria estándar, es decir, delegar la solución al programa existente.
Vi.
10

Bash - acerca de 50 35 bytes por idioma compilable

El truco es simplemente compilar, entonces no tiene que preocuparse por vincular errores de bibliotecas faltantes, y es más indulgente si solo tiene fragmentos de código.

¡Gracias a Shahbaz por formas más cortas!

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 ...


fuente
Como menciona el número de bytes por idioma compilable, puede estar interesado en líneas como:gcc -c $1 && (echo C; exit 0)
Shahbaz
¡Gracias, no soy muy bueno apretando realmente el código!
Seguro. El &&y ||en bash son realmente útiles y ayudan mucho a limpiar el código. De ninguna manera se usan para ofuscar, por lo que sería bueno aprenderlos.
Shahbaz
2
También puede pasar -fsyntax-onlypara verificar solo la sintaxis y omitir la compilación real.
peppe
7

18 lenguajes de programación, 1002 bytes, precisión: prueba por ti mismo :)

(sí, sé que esto no es golf de código, sino por diversión)

El programa busca fragmentos de código icónicos, las comprobaciones se ordenan de manera que las comprobaciones más claras están en la parte superior y los lenguajes de programación incrustados en otros lenguajes de programación están debajo (por ejemplo, HTML en PHP).

Obviamente, esto falla para programas como 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

Uso en nodo: coffee timwolla.coffee < Example.java

Demostración ( demostración en línea en 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
TimWolla
fuente
En mi computadora, esto no genera nada, ni siquiera en la entrada que obviamente debería funcionar. De acuerdo, podría estar haciendo algo mal ya que nunca antes había usado Coffeescript.
marinus
@marinus Tenga en cuenta que al ingresar código manualmente, debe enviar un EOF (STRG + D) para activar la ejecución. Generalmente: el detector debe al menos escupir tres signos de interrogación.
TimWolla
No, nada ¿Necesito pasar coffeealgún argumento? Acababa de intentar redirigir archivos a él, pero simplemente ejecutarlo y continuar ^Dtampoco hace nada.
marinus
@marinus Intente: npm install coffee-script && node_modules/.bin/coffee timwolla.coffee < timwolla.coffeeen una carpeta temporal, esto debería escupir APL. (suponiendo que tenga instalada una versión reciente de nodo y npm)
TimWolla
55
Comenzaré a usar omega en minúsculas más en mis programas que no son APL.
John Dvorak
4

Esta respuesta es una prueba de concepto, que probablemente no recibirá más trabajo de mi parte.

Se queda corto de varias maneras:

  • El resultado no es exactamente como lo solicita la pregunta, pero es lo suficientemente cercano y podría modificarse fácilmente para producir el resultado exacto requerido.
  • Hay varias formas de hacer que el código funcione mejor y / o mejores formas de representar las estructuras de datos.
  • y más

La idea es establecer una lista de palabras clave / caracteres / frases que puedan identificar un idioma específico y asignar una puntuación a esa palabra clave para cada idioma. Luego, verifique el (los) archivo (s) de origen para estas palabras clave y calcule los puntajes para cada idioma para el que encuentre palabras clave. Al final, el idioma con la puntuación más alta es el probable ganador. Esto también atiende a los programas políglotas, ya que ambos (o todos) los idiomas relevantes obtendrán una puntuación alta.

Lo único para agregar más idiomas es identificar sus "firmas" y agregarlas al mapeo.

También puede asignar diferentes puntajes a diferentes palabras clave por idioma. Por ejemplo, si cree que volatilese usa más en Java que en C, establezca la puntuación para la volatilepalabra clave en 2 para Java y 1 para 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;
    }
  }
}
ufis
fuente
4

Solo unas pocas generalizaciones amplias.

Creo que es bastante exacto.

Este es Ruby por cierto. Toma entrada (multilínea) 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
daniero
fuente
Creo que #include es un mejor predictor de c. ¿Qué pasa con #! / Bin / (ba)? Sh para los scripts bash / shell?
Trauma digital
@ Digital Trauma Sí, creo que tienes razón sobre #include. Por razones artísticas, no voy a captar el hash-bang donde explícitamente se deletrea el nombre del idioma.
daniero
#include es un comentario en iniarchivos yphp
Ismael Miguel
1
+1 por tener un prólogo, pero no C :)
SztupY
1
Agregaría \$\w+después del perl para detectar PHP. También (\w+)::~\1suele ser un destructor de C ++
SztupY
2

Javascript - 6 idiomas - alta precisión

Lenguajes actuales: Java, C, HTML, PHP, CSS, Javascript

Trabajo según el principio de que cada vez que una entrada satisface un criterio, se le da un puntaje, y en función de ese puntaje se dan los resultados.

caracteristicas:

  • No hay funciones integradas que determinen el tipo de idioma utilizado.
  • No declara de inmediato que el texto de entrada es el xidioma al ver una palabra clave.
  • Sugiere otros idiomas probables también.

Si siente que alguna de sus entradas de los programas (que he hecho hasta ahora) no se detecta o no obtiene resultados no válidos, informe y me complacerá solucionarlos.

Entrada de muestra 1:

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

Salida de muestra 1:

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

Explicación:

Esto debería haber fallado el programa y habría impreso PHP , pero dado que mi programa funciona sobre la base de puntajes, nada falla e identifica fácilmente Java en primer lugar, seguido de otros posibles resultados.

Entrada de muestra 2:

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

Salida de muestra 2:

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

Entrada de muestra 3:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

Salida de muestra 3:

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

El código:

// 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("----------------");
Gaurang Tandon
fuente