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

front + back

Navegando por la internet me encontré este ejercicio.

Como la respuesta que encontré me pareció interesante ( y fue diferente a la que dí inicialmente ) me pareció meritorio compartirselos.

Pongan sus respuestas y mañana escribo la solución que encontré y la comentamos.

No es nada obscuro ni nada, ni es Code Golf ni nada de eso, un simple ejercicio que por ser tan simple, tiene muchas posibles soluciones.

Ahi va:

// Divide una string en dos partes.
//
// Si la longitud es par, entonces el la primera mitad ( front )  y la segunda mitad ( back ) miden lo mismo.
// Si la longitud es non, entonces la letra de diferencia va en la primera mitad.
// Ejemplo: "abcde",  la primera mitad es: "abc" y la segunda mitad es "de"
//
// Dado 2 strings, a y b, escribir una función que regrese string que sea:
//
// a.front + b.front + a.back + b.back
//
//
// Prueba:

"abchodela".equals( frontBack("abcde", "hola") );

Que se diviertan.

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

interesante

De esos ejercicios que sirve hacerlos primero en un lenguaje que domines (como Java), luego en uno que no domines tanto (como Groovy) y luego en uno que estés aprendiendo y que sea distinto a los otros (como Scala)...

En Java para empezar.

En Java para empezar.

Imagen de ezamudio

Java y Groovy

De la manera más aburrida en ambos casos (sin funciones adicionales ni recursión ni nada de eso):

public String frontback(String a, String b) {
  int la = (a.length()/2)+(a.length()%2);
  int lb = (b.length()/2)+(b.length()%2);
  return String.format("%s%s%s%s", a.substring(0, la), b.substring(0, lb),
    a.substring(la), b.substring(lb));
}
def frontback(a,b) {
  int la=(a.length()/2)+(a.length()%2)
  int lb=(b.length()/2)+(b.length()%2)
  "${a[0..la-1]}${b[0..lb-1]}${a.substring(la)}${b.substring(lb)}"
}
Imagen de ezamudio

Scala

Y una manera un poquitito menos aburrida, en Scala (para que no fuera exactamente lo mismo que en Java, que bien lo pudo haber sido), definiendo un par de funciones inline:

def frontback(a:String, b:String):String = {
  def front(s:String):String = s.substring(0, (s.length()/2)+(s.length()%2))
  def back(s:String):String = s.substring((s.length()/2)+(s.length()%2))
  front(a) + front(b) + back(a) + back(b)
}
Imagen de ezamudio

Duh

La parte central de todo eso NO es partir las cadenas, sino calcular la posición en donde hay que partirlas... tomando eso en cuenta, aquí está mi segunda versión en los 3 lenguajes:

public int mitad(String s) {
  return (s.length()/2)+(s.length()%2);
}
public String frontback2(String a, String b) {
  return String.format("%s%s%s%s", a.substring(0, mitad(a)), b.substring(0, mitad(b)),
    a.substring(mitad(a)), b.substring(mitad(b)));
}

La de Java sigue estando algo aburrida... no hay más que agregar un método que calcule la mitad y luego invocarlo.

La de Groovy queda un poquito menos aburrida, si definimos un closure con el cálculo, dentro del mismo método:

def frontback2(a,b) {
  def mitad={ (it.length().intdiv(2))+(it.length()%2) }
  "${a[0..mitad(a)-1]}${b[0..mitad(b)-1]}${a.substring(mitad(a))}${b.substring(mitad(b))}"
}

Y la de Scala queda casi igual, solamente definimos una función inline adicional, que usamos dentro de las otras dos...

def frontback(a:String, b:String):String = {
  def mitad(s:String):Int = (s.length()/2)+(s.length()%2)
  def front(s:String):String = s.substring(0, mitad(s))
  def back(s:String):String = s.substring(mitad(s))
  front(a) + front(b) + back(a) + back(b)
}

En Groovy lo que puede estar interesante es pegarle mitad y frontback a la clase String, para al final poder hacerlo algo como "abcde".frontback("hola") y en Scala creo que se puede hacer algo similar pero con un mixin...

Imagen de AlexSnake

No quedo conforme

Bueno pues ya hice mi primer intento y este es mi resultado:

        public String frontBack(String stringA, String stringB){
               
                String frontA = "", frontB = "", backA = "", backB = "";
               
                int parteF = stringA.length()/2;
               
                if( stringA.length() % 2 == 0 ){
                        frontA = stringA.substring(0, parteF);
                        backA =  stringA.substring(parteF);
                }else{
                        frontA = stringA.substring(0, parteF + 1);
                        backA = stringA.substring(parteF + 1);
                }
               
                int parteB = stringB.length()/2;

                if( stringB.length() % 2 == 0 ){
                        frontB = stringB.substring(0, parteB);
                        backB =  stringB.substring(parteB);
                }else{
                        frontB = stringB.substring(0, parteB + 1);
                        backB = stringB.substring(parteB + 1);
                }
               
                return frontA + frontB + backA + backB;
        }

Hare el intento de reducir línea de código =P

Imagen de AlexSnake

Jajajaja

Mientras yo hacia mi primer intento ezamudio lo hizo no se cuantas veces con java, groovy y con Scala... no mas por que aun no sale Ryz sinooo tmb hubiera estado incluido en la lista.

Tu frontBack en Scala se ve

Tu frontBack en Scala se ve muy Javera todavía.

Como las funciones ( closures ) son elementos de primer nivel, se pueden declarar también como val

Y cuando el valor de retorno es claro se puede omitir y el compilador lo infiere:

def frontBack(a:String, b:String) = {
    val mitad = ( s: String ) => s.length / 2 + s.length % 2
    val front = ( s: String ) => s.substring(  0, mitad ( s  ) )
    val back  = ( s: String ) => s.substring( mitad ( s ) )
    front(a) + front(b) + back(a) + back(b)
}

Como s.length siempre regresa el mismo valor ( no tiene efectos secundarios ) se prefiere omitir los parentesis. También se pueden omitir los "." y hay una forma ( que no me salió ahorita ) en la que también se pueden omitir el parametro y usar "_" .

Lo que dices de agregar esa función a string se llama "implicit conversion" y para ello tienes que convertir el string en otro objeto que tenga el método:

implicit def string2FrontBack( o : String ) = new {
   def frontBack( b:String) = {
      val mitad = ( s: String ) => s.length / 2 + s.length % 2
      val front = ( s: String ) => s.substring(  0, mitad ( s  ) )
      val back  = ( s: String ) => s.substring( mitad ( s ) )
      front(o) + front(b) + back(o) + back(b)
  }
}

En este ejemplo el objeto se declara en línea también con new { etc. aunque aun no sé como se llame eso.

Y luego se puede usar:

"abcde"  frontBack  "hola"

Eso es más Scalish..

Por eso digo que en Scala lleva aquello de "escribir lo mismo de diferente forma" a otro nivel, porque mientras en la mayoría de los lenguajes se refiere a usar un diferente algoritmo para obtener los mismos resultados, en Scala literalmente es escribir lo mismo de una forma diferente.

Imagen de ezamudio

Otro modo

Gracias, estaba recordando lo de funciones anónimas pero no encontraba cómo usarlo en esas que declaré =>. Mientras estaba haciendo un frontback2, que recibe la función para calcular la posición como un parámetro:

def frontback2(a:String, b:String, m:(String)=>Int):String = {
  val front = (s:String) => s.substring(0, m(s))
  val back = (s:String) => s.substring(m(s))
  front(a)+front(b)+back(a)+back(b)
}

frontback2("abcde", "hola", (s:String)=>s.length/2+s.length%2)

Yo no hablaba de conversión sino de mixin, es otro desmadre Scalero. Voy a ver qué onda, luego. En Groovy sí encontré (bueno ya me la sabía) la manera de pegarle esos métodos a String:

String.metaClass.mitad = { (delegate.length().intdiv(2))+(delegate.length()%2) }
String.metaClass.frontback = {
  "${delegate[0..delegate.mitad()-1]}${it[0..it.mitad()-1]}${delegate.substring(delegate.mitad())}${it.substring(it.mitad())}"
}
"abcde".frontback("hola")
"abcde".frontback "hola"

EDIT: Lo del subguión en Scala no se puede usar para definir ninguna de las 3 funciones, pero sí para pasarle una función distinta a esta última versión que hice:

frontback2("abcde", "hola", (_.length/2)) //devuelve "abhocdela"

Intento

def frontBack(a:String,b:String):String= {
  val (la,lb)=(a.length/2 + a.length%2,b.length/2 + b.length%2)
  (a take la)+(b take lb)+(a drop la)+(b drop lb)
}
Imagen de rodrigo salado anaya

+1 por este tipo de cosas... (front + back )

Intente otras formas pero pues así me quedo : (....

public class FrontBack {

    public static void main(String[] args) {
        String s1 = "abcde";
        String s2 = "hola";
        System.out.println(getFrontBackMash(s1, s2, 0));
    }

    static String getFrontBackMash(String s1, String s2, int t) {
        String front = s1.substring(0, s1.length() % 2 + s1.length() / 2);
        String back = s1.substring(s1.length() % 2 + s1.length() / 2);
        if (t++ != 1) {
            back = getFrontBackMash(s2, back, t);
        }
        return t == 2 ? front + s2 + back : front + back;
    }
}

EDIT: Borre las que puse antes por que estaban mal.

Imagen de rodrigo salado anaya

Pffff

Pffff no pues nada que ver, me gustaron todas las que van hasta ahorita, pero ya leyendo los comentario la parte más ruda fue partir las palabras, he imaginar una manera que no fuera la más obvia, pues como muy seguido me pasa me confundí de que lado se ponía la letra que sobraba en los nones, pero en fin estuvo divertido.

Y la mía es muy tosca, no se me ocurrió algo más novedoso : S jejeje
Saludos y Chau...

Pues ya, tampoco tiene mucha

Pues ya, tampoco tiene mucha ciencia lo que encontré así que no voy a crear más expectativa.

Si aún desean poner su propia implementación simplemente no vean mi código ( las ideas se contagian )

El origen está en esta pregunta en Python

Mi idea original fue poner la implementación tal cual viene descrita en el problema:

"Si la longitud es non, el caracter extra se queda en el frente"

Entonces dije: divido entre dos y si es non, le sumo 1

               // la mitad  +      si es par          0   si es non 1
int index =  s.length() / 2 + ( s.lenght() % 2 == 0 ? 0 : 1 ) ;

O sea longitud entre dos , más 0 si es par o 1 si es non.

La solución que tiene ezamudio es lo mismo, sumarle a la mitad el módulo, que al ser módulo de 2 siempre será o 0 o 1

int la =  a.length() / 2 + a.length()%2;

Y casí todas las respuestas fueron en el mismo sentido. Como que ya estamos acondicionados a que si leemos aquello de "Si es par.." y se dispara el "Fuck it!! I'll use %"

Hasta aquí todo tranquilo no?

Pues bien, lo que me pareció interesante y la razón de este post en primer lugar es que hubo quién contestó:

int index = ( a.length() + 1 ) / 2;

Ahhh verdad? Esto es nuevo, porque nunca se usó el operador módulo. Y el resultado es idéntico.

Si es non y se le suma 1 al dividirlo entre dos da de todas formas el indice correcto:

"abcde"  longitud: 5
5 + 1 = 6
6 / 2 = 3
respuesta 3

"hola", longitud: 4
4 + 1 = 5
5 / 2 = 2
respuesta 2

Y obvio funciona perfectamente.

Acá va la versión en Java:

class FrontBack {
    public static void main( String ... args ) {
        System.out.println(
            new FrontBack().frontBack("abcde", "hola" ).equals("abchodela")
        );
    }
    private String frontBack( String a, String b ) {
        int ad = ( a.length() + 1 ) / 2;
        int bd = ( b.length() + 1 ) / 2;
        return a.substring( 0, ad ) + b.substring( 0, bd ) + a.substring( ad ) + b.substring( bd );
    }
}

Interesante no?

p.d. Ya que @AlexSnake lo menciona, esta sería la versión equivalente en Ryz ( IPA: /re:ies/ )

   frontBack( a: String, b: String ) : String {
      ad = a.length() .+ 1 ./ 2
      bd = b.length() .+ 1 ./ 2
      "%s%s%s%s".%( a .to: ad , b .to: bd , a .from: ad , b .from: bd  )
   }

Que sí compila en mi versión privada, la versión del repositorio necesita los parentesis siempre y el tipo de dato.

Usé unos métodos de extensión to: y from: nomás para que se vea más bonito y para presumir.

Este el el código completo:

sample.FrontBack {
   main(){
      frontBack("abcde","hola").println()
   }
   frontBack( a: String, b: String ) : String {
      ad = a.length() .+ 1 ./ 2
      bd = b.length() .+ 1 ./ 2
      "%s%s%s%s".%( a .to: ad , b .to: bd , a .from: ad , b .from: bd  )
   }
   to:( s: String , index : Integer) : String {
      s.substring( 0, index )
   }
   from:( s : String, index : Integer ) : String {
      s.substring( index )
   }
}

Resumen ( tl;dr )

La pregunta era: http://stackoverflow.com/questions/6947214/help-me-simplify-this-code-py...

La respuesta que encontré fue:

def front_back(a, b):
    ad = (len(a) + 1) // 2
    bd = (len(b) + 1) // 2
    return a[:ad] + b[:bd] + a[ad:] + b[bd:]

Que no usa el operador módulo %.

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