Comunidad PHPeros
Otros => Los Retos PHPeros => Mensaje iniciado por: good en 13 de Agosto de 2011, 18:17:00 pm
-
Hola
La idea es crear un script que parsee un string
la idea es crear como un pequeño lenguaje de programación. Las normas son:
Siempre que el script detecte un comentario (una linea que empieza con el carácter #) no la imprime
Si el programa encuentra un texto en forma $abc (donde abc es una secuencia no vacía de letras mayúsculas [A-Z], minúsculas [a-z], dígitos [0-9] o el carácter _ (subrayado)), entonces sabremos que estamos hablando de una variable, siempre que empiece con el carácter $.
Cada vez que el programa encuentre una variable ésta se substituirá por el valor de la variable, que por defecto será "nil" (en este problema no se dan valores a las variables, simplemente tienen un valor fijo)
En cualquier otro caso, el programa no substituye la secuencia
EJEMPLO DE ENTRADA:
# hola soy un comentario $variable $$hola
EJEMPLo DE SALIDA:
NADA (no se imprime nada, una linea en blanc)
EJEMPLO DE ENTRADA:
$soy_variable $$$ $y_yo_123
EJEMPLo DE SALIDA:
nil $$$ nil
EJEMPLO DE ENTRADA:
$$$ $ $$$ $ $asd $343_34-holamundohola
EJEMPLo DE SALIDA:
$$$ $ $$$ $ nil nil-holamundohola
No se pueden usar expresiones regulares
la solución puede ser por ejemplo una función, o un código con una variable con el string, eso no importa
fuente: olimpiada informática española
-
Hombre, lenguaje de programación está lejos lejos. Esto es sencillo de hacer con cualquier lenguaje. Si me animo, lo hago en C y a ver que tal queda.
Por cierto, la idea es buena :)
-
Hombre, lenguaje de programación está lejos lejos. Esto es sencillo de hacer con cualquier lenguaje. Si me animo, lo hago en C y a ver que tal queda.
Por cierto, la idea es buena :)
quizás php no sea el lenguaje más sencillo de usar para esto, yo recomiendo usar c++
-
Me refiero a que dices que vamos a crear un pequeño lenguaje de programación, cuando esto no es más que un programa que lee un archivo y lo modifica ;)
-
simplemente pido un script o programa que lea un string y la parsee, no quiero que sea muy complicado, esa es la idea
-
Por cierto, confío en que tengas la solución. Yo no voy a postear y haber hecho el trabajo que otro tenía que hacer hasta que haya alguna prueba.
-
tengo una solución de coste lineal en c++
-
Mañana editare este mensaje con la solucion porque la tengo pensada, pero ahora no puedo decirla porque estoy en el mobil :P
Pero basicamente primero borro los comentarios, luego busco las variables caracter a caracter de un array hecho con explode('$')
Pd: espero que esto sea un reto de verdad y no alguien que necesita un script ;)
EDIT:
Dejo el código por la mitad, porque la verdad es que sin expresiones regulares se me hace imposible :S
EDIT 2:
Te dejo el código usando una expresiones regulares (una sóla vez) para dar alguna idea a los demás y que se animen a hacerlo sin expresiones regulares :D
<?php
/*** Parser ****/
function showVars($string){
return preg_replace('/\$([a-z0-9_]+)/si', 'nil', $string); //sustituir variables por 'nil'
}
$string = '
#############################
#comentarios $algo $nil
#### asdasd \#adasd asd
Hola $nombre, espero que te sientas comodo en nuestro nuevo lenguaje de programacion :D
Se llama $nombre
#esto es un comentario';
$string = trim($string); //que los espacios no causen problemas
$ex = explode("\r\n", $string); //obtenemos cada linea en un array
$ac = count($ex);
for($i=0;$i<$ac;$i++){ // recorrer el array para eliminar los comentarios
if(substr($ex[$i],0,1)=='#'){ unset($ex[$i]); }
} //ya tenemos el code sin comentarios
$s = implode('<br />', $ex); //ponemos los saltos de linea en si sitio
$s = showVars($s); //obtenemos variables
echo $s; //y mostramos el resultado
?>
-
no es correcto, ten en cuenta que los comentarios no solo se declaran en el primer caracter, puede ser " # comentario"
además, creo haber dejado bien claro que no hay que usar expresiones regulares! XDD
-
Siento revivir esto, pero... tengo la solución: (hecho por mi desde cero)
<?
// $nil - Lenguaje creado con PHP
/*
- Reglas:
* $[algo] se reemplaza con "nil"
* Sin expresiones regulares
* Los comentarios empiezan con # y pueden estar al principio o al final (o en medio) de una línea
- NOTA:
* Hay un bug - no te acepta la variable si es el primer caracter del código...
*/
class Nil{
private $code; // code to parse
private $vars = array(); // code variables
var $anv = false; // true para aceptar $123, false para no aceptarlo
// definir codigo
function __construct($code){
if(!$code){ return false; }
$this->code = $code;
}
// devolver codigo; al ser protected no se puede acceder públicamente
function getCode(){ return $this->code; }
// procesar otro codigo
function setCode($code){ $this->code = $code; }
// borrar comentarios
function removeComments(){
$e = explode("\n", $this->code);
for($i=0,$c=count($e);$i<$c;$i++){
if($e[$i][0] == '#'){
unset($e[$i]);
}elseif(($s = strpos($e[$i], '#')) !== false){
$e[$i] = substr($e[$i], 0, $s);
}
}
$this->code = implode("\n", $e);
}
// reemplazar variables
function parseVars(){
if(strpos($this->code, '$') === false){ return; }
$v = 0;
while(($v = strpos($this->code, '$', $v + 1)) !== false){
$i = $v + 1;
if(!$this->anv && ctype_digit($this->code[$i])) continue;
while(ctype_alpha($this->code[$i]) || ctype_digit($this->code[$i]) || $this->code[$i] == '_') $i++;
$var = substr($this->code, $v, $i);
$this->code = substr($this->code, 0, $v).'nil'.substr($this->code, $i);
}
}
// devolver resultado final
function process(){
$this->removeComments();
$this->parseVars();
return $this->code;
}
}
echo '<pre>';
// variables normales
$nil = new Nil('Test de variables: $var'); // output: "Test de variables: $var"
echo $nil->process();
echo "\n\n\n";
echo "variables que empiezan por numeros - no permitidas:\n";
$nil->setCode('myVar: $123var'); // output: "myVar: $123var"
echo $nil->process();
echo "\n\n\n";
echo "variables que empiezan por numeros - permitidas:\n";
$nil->anv = true;
$nil->setCode('myVar: $123var'); // output: "myVar: nil"
echo $nil->process();
echo "\n\n\n";
echo "comentarios:\n";
$nil->setCode('#soy un comentario de una linea'); // output: ""
echo $nil->process();
echo "\n\n\n";
echo "comentarios en medio de la linea:\n";
$nil->setCode('hi bitches#comentario alone'); // output: "hi bitches"
echo $nil->process();
echo '</pre>';
?>
-
nmartin, un dato sobre POO. Los constructores no deben retornan valores. Si ese false que retorna tu constructor es sinónimo de "error", mejor arroja una Exception.
-
Es tan sencillo como utilizar ob_start, si me animo hago luego una Parser.
-
No sé si será la solución más optima pero llegué a esto en js:
var s1 = " $ $$$ $Variable_3213-321 # hola soy un comentario $variable $$hola";
var s2 = "$soy_variable $$$ $y_yo_123";
var s3 = "$$$ $ $$$ $ $asd $343_34-holamundohola";
//Sin Regex
function nrTrace(str) {
var r="",
g=str.split("\n");
for(var i=0;i<g.length;i++) {
var l=g[i].split(" ");
for(var j=0;j<l.length;j++) {
if(l[j].length>0) {
if(l[j].indexOf("#")>=0) break;
else if(l[j].indexOf("$")>=0) {
var n = l[j].indexOf("$");
if(l[j].charAt(n+1)!="$" | "-" && l[j].length>1) {
var y = l[j].split("-");
for(var u=0;u<y.length;u++) {
if(y[u].charAt(0)=="$") r+="nil";
else r+="-"+y[u];
}
}else r+=l[j];
}
}
r+=" ";
}
}
return r;
}
//Con Regex
function trace(str) {
var r="",
g = str.split(/\n/g);
for(var i=0;i<g.length;i++) {
var l = g[i].split(/\s/g);
for(var j=0;j<l.length;j++) {
if(l[j].indexOf("#")>=0) break;
else {
var v = l[j].replace(/\$[^$][0-9_a-z]+/,"nil");
r+=v+" ";
}
}
}
return r;
}
console.log("Sin Regex");
console.log(nrTrace(s1));
console.log(nrTrace(s2));
console.log(nrTrace(s3));
console.log("---------");
console.log("Con Regex");
console.log(trace(s1));
console.log(trace(s2));
console.log(trace(s3));
Lo probé en node.js y me devuelve:
Sin Regex
$ $$$ nil-321
nil $$$ nil
$$$ $ $$$ $ nil nil-holamundohola
---------
Con Regex
$ $$$ nil-321
nil $$$ nil
$$$ $ $$$ $ nil nil-holamundohola
-
Lo he hecho en Java:
package parser;
public class Parser {
public static void main(String[] args) {
System.out.println(analize("esto $mola #mazo"));
}
public static String analize(String text) {
String analized = "";
if(text.startsWith("#")) {
// Nada
} else {
for(String linea : text.split(" ")) {
if(linea.startsWith("$")) {
String a = "";
if(linea.contains("-")) {
a = "-".concat(linea.split("-")[1]);
}
if(linea.replace("$", "").isEmpty()) {
analized += linea;
} else {
analized += "nil";
}
analized += a.concat(" ");
} else if(!linea.startsWith("#")) {
analized += linea.concat(" ");
}
}
}
return analized;
}
}