style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Ejercicio (como) para volverse loco

Resolviendo una pregunta en otro lado llegue después de un par de iteraciones a una solución bastante extraña para resolver el siguiente problema:

"Crear un método que reemplace todas las letras L encontradas en HELLO WORLD con una x y que la x aparezca incrementada en cada ocurrencia de L"

Ejemplos:

Entrada: "HELLO WORLD"
Salida:  "HExxxO WORxxxD"
Entrada: "HELLO LAZY LIMBO WORLD"
Salida:  "HExxxO xxxAZY  xxxxIMBO WOxxxxxR"

Restricciones: Únicamente se pueden utilizar los siguiente métodos de la clase String:.length; .indexOf; y.substring(); y claro el resto del lenguaje ( for, while, operador + variables etc. ). Ninguna otra clase, ningún otro método.

Mi solución solo dos sentencias:

public static String replace( String in ){    
  //??
  //??
  return in;
}

Pff... para volverse loco.

Ahi se los dejo de tarea.

Update Le había puesto que regresaba XXX en unos y xxx en otros. Es siempre con la misma "x" ( cualquiera de las dos )

Mi error, corregido. Gracias wishmaster77 por notarlo.

EDIT: (ezamudio) Si piensan resolver el ejercicio, no vean todavía los comentarios, porque ya hay algunas soluciones ahí; primero resuélvanlo y luego ponen su solución en los comentarios, para compararla con las que ya están...

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Chale

Encontré una solución pero en 3 sentencias (1 declaración, 1 condición de ciclo, y la transformación), y sin length()...

A menos que el ciclo y la transformación se cuenten como una sola sentencia, pero pues es un ciclo con un bloque de una sola sentencia, yo los contaría como dos...

Jajaj también estas bien 'che

Jajaj también estas bien 'che loco mano...

Si, es sin length y estás a un pasitito de transformar de 3 en 2 :)

Por cierto luego encontré uno en una sola sentencia, pero ya está muy fumada ( aunque no tanto si lo tuyo lo tuyo , es programar en lisp )

ajajaj

Imagen de ezamudio

aaaaah ya sé!!!!

Con for en vez de while, metes la declaración al for y queda en 2. Ya lo tengo. Ahora pensaré en ese de una sentencia... con recursión seguramente...

Imagen de ezamudio

Recursiva

(si ya sé que yo mismo estuve jodiendo con que es "recurrente" pero entre devs decimos muchos pochismos)

Con recursión se puede hacer en una sola línea, pero hay que hacer la función de dos parámetros: la cadena a transformar y la cadena de reemplazo para la L. Y pues queda un poquito más flexible porque entonces puedes reemplazar la L con alguna otra cosa (de un solo caracter).

Esperaré unas horas más a ver si alguien más se anima, pero si sigue igual de popular este post para las 2pm ya publico mis soluciones.

Pos claaaaro... jejejej el

Pos claaaaro... jejejej el for tiene tres partes el while una nomás :) -> 1 sentencia.

Xacto la otra es la versión recursiva. Pero en Java se ve como perl :S

Imagen de ezamudio

conditional statement

Las sentencias condicionales cuentan como una sola, no? porque pues tienen que tener tres partes a fuerzas... o cuentan como 2? o como 3? porque mi versión recursiva de una línea es con una sentencia condicional.

Mi resultado

Me estorba esa declaracion de String x, estoy viendo si la puedo desaparecer:

        public static String replace (String in) {
                for (int contador = 0, posicion = 0;(posicion = in.indexOf ("L")) > -1;contador ++) {
                        String x = "";
                        for (int i = 0; i <= contador; i++) {x += "x";}
                        in = in.substring (0, posicion) + x + in.substring (posicion + 1, in.length ());
                }

                return in;
        }

Cuentan como 1... una

Cuentan como 1... una sentencia aun cuando tenga ternarios anidados.

recursividad?

Me late que va orientado mas a la recursividad, aun asi no puedo sacarlo en dos lineas, esta bueno esto!

Imagen de Shadonwk

Mi solución

yo no estoy tan loco me quedo asi:

public static String replace( String in ){    
                  String tem,salida="";
                  int contador=1;;
                  for(int i=0; i<in.length();i++){
                          tem=in.substring(i, i+1);
                          if(tem.equals("l"))
                          {
                                  for(int j=0;j<contador;j++){
                                          salida += "x";  
                                  }
                                  contador++;
                          }else{
                                  salida = salida +tem;
                          }
                  }
                  return salida;
        }
Imagen de ArenasMx

soluciones

bueno bueno lo que me agrade de la programación es que puedes tener diferentes soluciones a un mimo problema, y habia pensado en un while y una sentencia... no lo había pensado en algo recurrente....

Recurrente?

Puagh.. prefiero oir "recursivo" aunuque no existe ( ya ves lo que provocas enrique? ) jajajaj </broma>

De hecho no hay taaantas opciones, todas son el mismo algoritmo ( al menos los que he visto ) solo que implementado de forma diferente.

En mis propias palabras

1.- Comparar cada caracter
2.- Si coincide reemplazar con x
3.- Incrementar las x's
4.- Repetir.

Weno creo que si me ví demasiado abstracto.

My recursiva ( no quería hacerla, por que me daba flojera ) es de 1 sentencia con 3 ternarios anidados.

Imagen de ezamudio

3 ternarios?

No manches es demasiado! yo hice una recursiva con solamente 1 ternario! pero la función requiere 2 parámetros...

¿Debe ser así? Entrada:

¿Debe ser así?
Entrada: "HELLO WORLD"
Salida: "HEXXXO WORXXXD"

Entrada: "HELLO LAZY LIMBO WORLD"
Salida: "HExxxO xxxAZY xxxxIMBO WOxxxxxR"

¿O así?
Entrada: "HELLO WORLD"
Salida: "HEXXXO WORXXXD"

Entrada: "HELLO LAZY LIMBO WORLD"
Salida: "HEXXXO XXXAZY XXXXIMBO WORXXXXXD"

*EDIT: No @Oscar, osea ve el órden en "Hello lazy limbo world" tú pones "Hexxxo xxxazy xxxximbo woxxxxxr" y yo sugerí: "Hexxxo xxxazy xxxximbo worxxxxxd"

wishmaster77 My bad... es

wishmaster77 My bad... es con uno o co el otro.. me equivoque.

Fixing...

Sepa... no tendrás un

Sepa... no tendrás un ternario mezclado con algún loop ? jejeje .. Propongo que lo veamos el lunes, hay quién le da ganas de hacer eso el finde...

ok!...entonces ya me quedó,

ok!...entonces ya me quedó, pero en 2 for un if, una declaración, un incremento y una asignación.

PERO es capaz de hacerlo con cualquier letra, no sólo la L jejejeje. ¿Se puede postear el resultado?

Imagen de ezamudio

Postealo

Esa es la idea, empezar a ver las soluciones que han hecho los miembros de la comunidad.

Imagen de bimboso_d

Wiii

Jajaja si me salio.
Tal vez no es lo mas eficiente, ni lo mas estetico pero me salio jajajajaja

public static String modificando(String entrada){
        String resultado = "";
        int tamaño = entrada.length();
        int inicio  = 0;
        int nx = 1;
        String temporal = entrada;
        while(temporal.indexOf("L")!=-1){
            resultado = resultado + temporal.substring(0,temporal.indexOf("L"));
            for(int a = 0; a<nx; a++){
                resultado = resultado + "x";
            }
            nx++;
            inicio = temporal.indexOf("L")+1;
            tamaño = temporal.length();
            temporal = temporal.substring(inicio,tamaño);
        }if(temporal.length()!=0){
            resultado +=temporal;
        }
        return resultado;
    }

creo que respete las restricciones jajajaja ¿no?

Imagen de AlexSnake

Seria bueno

Ojala que se denla respuesta el lunes, yo quiero intentar hacer el ejercicio pero estoy algo saturado del trabajo. Sirve que también entran algunos tantos el fin de semana y se publican mas respuestas.

Saludos.

Entendido:

Entendido: http://pastebin.com/eD0HcNWE

Revisenlo pues =)

Imagen de rodrigo salado anaya

:( si se pa locos

public class Main {
    public static void main(String[] args) {
        System.out.println(replace("hello world", "x"));
    }

    public static String replace(String in, String xs) {
        int lPosition = in.indexOf("l");
        if (lPosition != -1) {
            in = in.substring(0, lPosition) + xs + in.substring(lPosition + 1);
            xs += xs;
            in = replace(in, xs);
        }
        return in;
    }
}

UPDATE: Chin por las prisas un ERROR jejeje, est es el bueno

public class Main {

    public static void main(String[] args) {
        System.out.println(replace("hello world", "x"));
    }

    public static String replace(String in, String xs) {
        if (in.indexOf("l") != -1) {
            in = in.substring(0, in.indexOf("l")) + xs + in.substring(in.indexOf("l") + 1);
            xs = xs + "x";
            in = replace(in, xs);
        }
        return in;
    }
}

Imagen de ezamudio

verborrea

Ya veo por qué nos tiran tanto a los javeros con que somos unos choreros y que en Java hay que escribir mucho código... interesante ver las soluciones que han publicado hasta ahora pero ninguna ha tenido menos de 4 líneas! Las más compactas hasta ahorita son la de java.daba.doo y la de rodrigo salado...

Imagen de rodrigo salado anaya

mmmm pues sin comentarios... jejeje

Pues que les digo esto esta muy YUPY jejeje....

public static String replace(String in, String xs) {
        return in.indexOf("l") != -1 ? replace(in.substring(0, in.indexOf("l")) + xs + in.substring(in.indexOf("l") + 1), xs + "x") : "";
    }

UPDATE: Lo que no me latio es que tenga un "x" hardcoreada... -1 por eso :P

Imagen de ezamudio

Mi solución

Aquí está mi solución. Para los que no la quieran ver, pues no la pueden ver y ya. Para los que la quieran ver, arrastren el mouse sobre el área donde parece que no hay nada para que vean el texto.

public static String r2(String s) {
	for (String x = "x"; s.indexOf("L") >= 0; x = x + "x") {
		s = s.substring(0, s.indexOf("L")) + x + s.substring(s.indexOf("L") + 1);
	}
	return s;
}

Y la versión de una sola línea:

public static String r3(String s, String x) {
	return s.indexOf("L") >= 0 ? s.substring(0, s.indexOf("L")) + x + r3(s.substring(s.indexOf("L")+1), x+x.substring(0,1)) : s;
}

No es lo más entendible del mundo, pero pues me obsesioné un poco con lo que decía Oscar de que le había salido en dos líneas.

Imagen de ezamudio

la probaste?

Rodrigo, probaste tu función? porque según yo devuelve la cadena incompleta (por el último return de cadena vacía)

Imagen de rodrigo salado anaya

@OscarRyz, @ezamudio.

si pudieran programarías con el efecto mariposa, LOL jejeje, en una ocasión me mostraron esa caricatura y era algo con editores ... regresando al tema, si le metemos un "l" al mio y creo que a varios más se truena gachisimo la memoria, esto es justo para el un tema que saco Oscar... por ejemplo

public class Main {

    public static void main(String[] args) {
        System.out.println(replace2("hello world", "l"));
    }

    public static String replace2(String in, String xs) {
        return in.indexOf("l") != -1 ? replace(in.substring(0, in.indexOf("l")) + xs + in.substring(in.indexOf("l") + 1), xs + "x") : in;
    }
}

/*
run:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:3209)
        at java.lang.String.<init>(String.java:215)
        at java.lang.StringBuilder.toString(StringBuilder.java:430)
        at orscarchalanger.Main.replace(Main.java:19)
*/

UPDATE: Lo siento chicos, gracias Chochos, me falto el 'in' al final, no le digas a @citADN, si no me va a regaña por no estar trabajando jejejeje

@

Imagen de ArenasMx

ohhhhh

sorprendido por la solución de ezamudio.... el for era algo que había pensado pero pensé que su estructura era rigida y que solo podias poner algún valor numérico o alguna referencia d este tipo pero no imagine que pudiera aceptar algo diferente como un string

Imagen de ezamudio

claro

Si tratas de reemplazar la L con otra L pues nunca va a terminar, y la versión recursiva va a acabarse el stack hasta tronar como Jenga. La única manera de arreglar eso es validar que tu xs no sea L, tal vez arrojar una IllegalArgumentException en ese caso.

Y cómo está eso de programar con el efecto mariposa? Digo, lo conozco (explicación sencilla de teoría del caos) pero aplicado a programación?

Imagen de ezamudio

un solo ternario

Oscar, ya viste que sí se puede en una sola línea con un solo ternario?

Lo del efecto mariposa me

Lo del efecto mariposa me parece que fue una "re-interpretación" de Rodrigo.
jejeje

Quizá se refiere a que los verdaderos programadores utilizan mariposas para programar ( no nano, ni emacs, ni vi, ni siquiera, ed o cat )

http://xkcd.com/378

Viendo la solución creo que hice demasiadas validaciones en mi version recursiva.

La del for,no necesita cuerpo ( solo un ";" )

public static String replace( String in ){     
  String x = ""; // declaración 1 sentencia
  for( int i = 0;  ( i = in.indexOf('L',i)) > -1 ; in = in.substring(0,i++) + ( x=x+'x' ) + in.substring(i) ); // for 2da sentencia
  return in;
}

Por cierto, si se usa indexOf( char c, int from ) se evita reescanear toda la entrada de nuevo.

Me voy a dar otro chance para mi versión recursiva :)

Chau!

Sobre el ternario: Si me dí vuelo validando condiciones innecesarias

Ahi pa'lunes

Imagen de ezamudio

Una línea

Ah entonces ya sé cómo podemos hacerlo de una sola línea, iterativo. Mezcla de tu solución con la mía, Oscar:

public static String r4(String s) {
	for (String x="";  s.indexOf('L') > -1 ; s = s.substring(0,s.indexOf('L')) + ( x=x+'x' ) + s.substring(s.indexOf('L')+1) );
	return s;
}

De hecho cuando empecé a hacerlo tenía un while, la inicialización de "x" y en el cuerpo la concatenaba como está aquí. Pero luego la pasé al for, y quedó la solución que puse originalmente. Pero esta me gusta más, está como para entrevista, presentar esa línea y que te digan qué hace...

Sé que usar la variante de indexOf con posición inicial evita escanear toda la entrada, pero vamos, no estábamos compitiendo por desempeño sino por menos líneas, no? Al menos eso entendí al principio... como segunda parte está bueno pensarlo en performance y también en uso de memoria (concatenar es muy ineficiente)

Al fin 2 lineas: public

Al fin 2 lineas:

public static String reemplazar(String cadena, String letra, String reemplazo){
                if(cadena.indexOf(letra) != -1)
                        cadena =
                                        cadena.substring(0, cadena.indexOf(letra)) +
                                        reemplazo +
                                        reemplazar(
                                                  cadena.substring(cadena.indexOf(letra) + 1),
                                                  letra,
                                                  reemplazo+reemplazo.substring(0,1)
                                        );
                return  cadena;
}

Ya ahí estan las 2 =) recursiva e iterativa: http://pastebin.com/wsKsdibz

Imagen de ezamudio

wishmaster

Si usas operador ternario, puedes convertir tu función a una sola linea.

mmm...veamos

mmm...veamos

Ahora si ya completo, gracias

Ahora si ya completo, gracias a @Ezamudio por la idea del ternario, y pues ahora si tengo mis 3 implementaciones. http://pastebin.com/cXDJbDkR

Imagen de rodrigo salado anaya

@ezamudio... a chirriones

Hice un copy&paste de tus respuestas, y no hicieron nada :P. Soy yo?
La onda creo que es que nunca se le asigna nada modificado a 'in'...

Imagen de ezamudio

rodrigo

Las probé todas, no iba a subir código sin compilar y probar... mis versiones ni siquiera dicen in, la variable es s... no imprimen nada, hay que llamarlas imprimir el valor de retorno

Imagen de rodrigo salado anaya

@ezamudio. Va

Sí ezamudio, los voy a probar bien vale...

Están muy chidos ya los corrí, fue un error de teclaso :P

Imagen de jvidales

Mi propuesta

        public static String replace(String in, String r)
        {
                if (in.indexOf('L') > -1)
                        in = in.substring(0, in.indexOf('L')) + r + replace(in.substring(in.indexOf('L') + 1), r + "X");
                return in;
        }

Tuve que aumentar un parámetro, ustedes cuenten cuantas líneas son la primera llamada sería

replace(hw, "X")

PD: Que conste que vi las otras soluciones despues de postear la mia
Para el Chochos: Hago constar que la revisión de las soluciones previas fué posterior a la publicación de la propia

Imagen de ezamudio

Julia

Para ti aplica lo mismo que para wishmaster: si cambias tu if por operador ternario, te queda de una línea.

Si no quieren hardcodear* la X, pueden poner r + r.charAt(0).

Ya al final en términos de tamaño, me gusta más la versión iterativa que es amalgama de lo que puso Oscar con lo que había puesto yo. Un for sin cuerpo, que pues se debe considerar una sola sentencia...

* palabra reservada de Español++

jajaja en ves de que Rodrigo

@jvidales jajaja en ves de que Rodrigo se fuera a trabajar te trajo acá ... jajaja ta vaciado eso.

Que conste, que no se trata de líneas, sino de "sentencias" ( o statements )

Pues un statement como el for puede partirse en tres líneas.

Pues bien, que bueno que les parecio interesante el reto. La verdad es que cuando iniciamos parece casi imposible, pero así son muchas cosas, una vez realizadas no lo parecen tanto.

Aquí está el post original ( voten por mi respuesta :P ) Replacing a character every ocurrence in a string in Java Como podrán ver, solo dos personas lo pusimos en tan pocas sentencias, y quizá si aquí no hubiera llegado diciendo "en 2!!!" hubiera pasado algo similar.

p.d. No se puede usar charAt no está en la lista de métodos permitidos.

Chau!

Imagen de ezamudio

charAt

Cierto, no se puede usar charAt. Bueno entonces x.substring(0,1), ese sí se puede

Re: Julia

Pues si, ya dejé la versión completa de la clase en pastebin (de la primer versión hasta la recursiva con ternario).

Imagen de Nopalin

jaja chale

Al parecer solo yo me la crei que era con un solo parametro jeje.

Pues lo que hize fue algo horroso, lo que se trata de evitar en java (por eso es verboso, algo que agradezco), pero en fin, esta es mi solución sin ser recursiva

public class ReemplazaChar {
       
        public static void main(String[] args){
                System.out.println("HELLO WORLD => " + replace("HELLO WORLD"));
                System.out.println("HELLO LAZY LIMBO WORLD => " + replace("HELLO LAZY LIMBO WORLD"));
        }

        public static String replace(String str){
                for(String i="1", tmp="";
                        str.indexOf('L') > -1
                                && ((tmp = str.substring(0, str.indexOf('L'))) != null)
                                && ((str = str.substring(str.indexOf('L')+1, str.length())) != null);
                        str = tmp + str + ((i = Integer.toString(Integer.parseInt(i)+1)).substring(0, 0)) ){
                        for(int j=0; j<Integer.parseInt(i); j++){tmp = tmp + "x"; }
                }
               
                return str;
        }
}

Es interesante observar como cada uno piensa de manera muy distinta.

Sobres

Imagen de ezamudio

parámetros

yo también hice mi función de un solo parámetro. La iterativa, al menos. La recursiva requiere un segundo parámetro.

Esta de Nopalin creo que es la más enredada que he visto, pero ilustra un punto no muy conocido: en un for se pueden inicializar varias variables del mismo tipo.

Wow, genial @ezamudio!

Sorprendente los códigos de Enrique. Me gusto el del for sin cuerpo mas que el "recursivo" tiene mas estilo (para mi)

Imagen de ezamudio

for sin cuerpo

Gracias; ese último ya fue mezcla de lo que hizo Oscar con mi for original. Quería hacer un for con 2 inicializadores: uno para el contador y otro para las X, pero solamente se pueden inicializar variables del mismo tipo (es una sola declaración a fin de cuentas). Nopalin hizo algo así pero tuvo que hacer el indicador de posición como cadena. Tal vez se pueda integrar eso a una sola línea, pero a fin de cuentas creo que el costo de estar convirtiendo el indicador de posición entre String y entero para cada L encontrada, será mayor que el costo de escanear completa la cadena desde el inicio buscando una nueva L.

Imagen de ezamudio

Segunda ronda

Ahora podrían hacer la función pero en vez de enfocarse a menos sentencias, enfocarse a dos cosas (pueden tirarle a una, a la otra, o a una combinación de ambas):

1. Velocidad
2. Uso de memoria (o sea, que use la menor memoria posible).

Las variantes que hemos puesto, tanto iterativas como recursivas, de una o dos líneas, honestamente no son óptimas ni en uso de CPU ni en uso de memoria. Estuvo muy interesante porque se trataba de aprovechar al máximo el conocimiento del lenguaje y de algoritmos en general, para realizar el algoritmo de la forma más compacta posible en cuanto a código, pero nada más...

Otra variante: usando expresiones regulares...

Imagen de ArenasMx

según

pues segun lo que recuerdo de mi clases de analisis de algoritmos decian que los algoritmos que recurrentes son los que tienes una función asociada de nlogn o logn imagino que esto sera para la velocidad, para uso de la memoria pues lo veo un poco complicado porque tendrias o se tendria que definir el entorno ademas con las diferencias de equipo no es lo mismo usas 4 mb de memoria, en equipo que tienes ddr3 1600 a un equipo con memorias ddr2 433 vamos que tiene y va a existir una diferencia.....minima pero existe......

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">