Obteniendo todas las posibles “palabras” de 7 letras (o menos)

Últimamente, el juego al que más le dedico tiempo (además de Tekken) es a Angry Words (apalabrados en español). Con eso que me gusta Scrabble desde hace mucho, me relaja mientras voy en el tren y al mismo tiempo me ayuda a practicar mi vocabulario.

De la misma manera, le he estado dedicando tiempo a aprender Haskell, ya que veo que algunas cosas de PLN podrían ser implementadas más fácilmente con programación funcional.

Buscaba un problema que me ayudara a practicar Haskell, a dar mis primeros pinitos en el lenguaje. Y mientras disfrutaba el mencionado juego y veía que es más de “ponle lo que sea a ver si pega” en vez de “piensa en alguna palabra interesante”, se me ocurrió crear un programa que, dada una serie de letras, mostrara todas la combinaciones posibles entre ellas. Lo veía fácil y factible, por lo que me decidí a poner manos a la obra.

¿Qué tan difícil puede ser?… me pregunté. Y aunque no es algo tan complicado, sí me tomó más tiempo del que pensaba debido a que había que hacer el cambio a programación funcional y no a imperativa.

Primero, a definir el algoritmo:

Tomemos una palabra de 3 letras (por conveniencia, más adelante verán por qué), digamos “ola”. ¿Qué es lo que quiero obtener? La lista de posibles permutaciones con esas 3 letras, es decir: ola, oal, loa, lao, aol, alo. Aquí me di cuenta de un patrón: tomo una letra de la palabra, la pongo al principio, y simplemente tomo las otras 2 letras restantes y les cambio el orden. Para comenzar, tomo la “o” como la letra principal, entonces me quedo con “la”, y las únicas combinaciones posibles son “la” y “al”; después, agrego la letra principal “o” y la pongo al principio de cada palabra, obteniendo “ola”,”oal”. Continúo con la siguiente letra, la “l”, la tomo como principal, quedándome “oa”, de la cual obtengo “oa” y “ao”; le pongo la “l” al principio de cada una y obtengo “loa”,”lao”. Por último tomo la “a” como letra principal, lo que me deja con “ol” como el resto, obteniendo “ol” y “lo”; le pongo la “a” al principio de cada una y resultan “aol”, “alo”. Juntando todos los resultados parciales, obtengo la lista de palabras que estoy buscando.

Con la definición anterior, recursivamente se pueden analizar palabras de cualquier longitud. ¿Buenas noticias para los que juegan apalabrados? En teoría, si es que tienen la paciencia de ver todos los resultados. ¿Cuántos son? Saquemos cuentas:

Una palabra de 3 letras resultó en una lista de 6 palabras. ¿Cuántas resultarán de una de 4? Como lo que buscamos son permutaciones, la fórmula es sencilla:

n!

Revisemos: 3! = 3x2x1 = 6. ¡Bien! Si cuadra el resultado

Entonces, con 4 letras tendremos: 4! = 4x3x2x1 = 24 Todavía no son muchas…

Con 5 : 5! = 5x4x3x2x1 = 120 ya da flojera ver tantas permutaciones…

¿Y con 7? Pues 7! = 7x6x5x4x3x2x1 = 5040 Está bien que no haya límite de tiempo en cada jugada de apalabrados, pero qué flojera (o ganas de ganar) de aquél(la) que se ponga a leerla cada vez.

¡Ajá! Dirán ustedes: ¿qué pasa si hay letras repetidas? Obviamente habrá palabras repetidas también, lo cual reduce nuestra lista. ¿A cuánto? Oh benditas matemáticas:

n!/(a!b!c!…)

En donde a es el número de veces que se repite una letra, b es el número de veces que se repite otra, c es el número de veces que se repite otra… y así sucesivamente.

Supongamos que tenemos las letras “atajada” (si las tienen, ¡no la piensen y jueguen esa palabra!). La letra “a” se repite 4 veces, entonces, tendremos:

7!/4! = 7x6x5 = 210

Quizá pude haber pensado el algoritmo con una palabra de 4 letras desde el principio, y aunque sí revisé a mano después, me era más fácil iniciar con una de 3 (sólo 6 posibles permutaciones).

Luego, a hacer el programa. El resultado, a sabiendas de que puede haber una mucho mejor implementación, es una belleza de 18 líneas de código (y porque puse doble enter en algunos lugares):

Continue reading “Obteniendo todas las posibles “palabras” de 7 letras (o menos)”

XMonad: Cambiar el nombre del layout que se muestra

Hace tiempo escribí sobre XMonad y un xmonad.hs básico en donde mostraba cómo mostrar íconos en vez del título del layout. Esta vez esalgo similar, pero como ahora sí estoy estudiando Haskell en forma, ando buscando cómo hacer lo que quiero con guards:

En uno de los escritorios estoy usando LayoutCombinators para combinar 2 layouts (concretamente simpledTabbed y DragPane Horizontal). Al mostrarse el nombre del layout aparece lo siguiente:

“combining Tabbed Simplest with DragPane Horizontal 0.1 0.099999999”

Debido a su longitud, me quita espacio del título de la ventana activa, por lo que pensé hacer un shorten, pero después recordé que en la laptop hago pattern matching para mostrar un ícono en vez del nombre del layout, por lo que pensé hacer algo parecido: si el nombre del layout comienza con “combining”, muestro un nombre que yo defina, y en cualquier otro caso muestro el nombre original.

El layout quedó así:

myXmobarPP h = xmobarPP
             { ppOutput = hPutStrLn h
             , ppCurrent = xmobarColor "green" "" 
             , ppHidden = xmobarColor "#5f7962" ""
             , ppVisible = xmobarColor "#f4a460" ""
             , ppUrgent = xmobarColor "#cc0000" "" . wrap "*" "*"
             , ppSep = " | "
             , ppWsSep = "  "
             , ppLayout = xmobarColor "#5CBAF5" "" .
                          (\lName -> showLayoutName lName)
             , ppTitle = xmobarColor "white" "" . shorten 150
             }

showLayoutName :: String -> String  
showLayoutName a | Just rest <- stripPrefix "combining" a = "Tabbed + DragPane H" 
showLayoutName a = a

Donde lo que quiero hacer está en ppLayout: una expresión lambda para revisar si el título comienza con “combining” o no. Esa revisión la hago en la función showLayoutName con la función stripPrefix, que recibe una lista y regresa otra lista que contiene los elementos después del prefijo indicado si es que existe, o Nothing en caso contrario. Si el título del Layout comienza con “combining”, regreso “Tabbed + DragPane H”, y si no, simplemente regreso lo que me llegó.

Intenté hacerlo con guards, pero nomás no me compiló el código, y como estoy en el trabajo, no me dio más tiempo de probar, por eso lo implementé como aquí se muestra.

Si quisiera hacerlo en Scala, el código quedaría así:

val xmobarColor = (bgColor: String) => (fgColor: String) => (output: String) => {
  // Hacer algo con los parámetros y regresar un String
  ...
}

val showLayoutName = (layout: String) => {
  layout.startsWith("combining") match {
    case true => "Tabbed + DragPane H"
    case _ => layout
}

// Asignando todo a ppLayout

val ppLayout = ((xmobarColor("#5CBAF5")("")) compose showLayoutName)

// Siendo layoutName el nombre del layout actual

ppLayout(layout)

Aunque sigo siendo novato en Scala (y para esos fines, en programación funcional), me late más la forma concisa de Haskell. Hacer function composition en scala es agregar demasiadas palabras (aunque si usara scalaz todo cambiaría), mientras que en Haskell el currying, la aplicación parcial y la composición se hacen sin mayor complicación.

Sigo estudiando y practicando.

¿Sabías que… ? – Parte 13

Me gustaría mucho saber si el ¿sabías que…? de esta ocasión también se acostumbra o lo han visto en otros países.

Sin más preámbulos:

¿Sabías que cuando entras a un café o restaurante en Japón lo primero que llega a tu mesa es un vaso de agua, y puedes tomar toda la que quieras porque es gratis?

Explico:

  • Cuando llegas a un restaurante, los meseros te dan la bienvenida y te dan un vaso de agua, incluso antes de que ordenes algo. Generalmente es un vaso pequeño, pero siempre hay jarras en las mesas o bien puedes pedir tanta agua como lo desees. El agua no tiene costo.
  • Si con tu orden no pides ninguna bebida, por lo general te sirven más agua.
  • En Japón, lo que nosotros conocemos como “agua natural” es llamada “agua mineral” (ミネラルウォーター). De ahí que los japoneses se confundan cuando salen del país y piden agua mineral esperando obtener agua común y corriente.
  • Aquí se puede beber el agua directamente del grifo (de la llave) sin problema, aunque algunos japoneses prefieren hervirla primero.

Cuando recién llegué a este país, el hecho de que en las cafeterías me sirvieran agua sin haber ordenado nada sinceramente me sorprendió, sobre todo porque vienes con la idea de México: “chin… me lo van a cobrar”.

¿Saben ustedes de algún otro país en donde se acostumbre algo similar?

Y me mudé

Ya es marzo. El paso del tiempo es curioso: a veces lo siento muy rápido, otras demasiado lento. Sin embargo, no se detiene, y con él, los planes se llevan a cabo.

El pasado domingo me mudé. Sigo viviendo en Tokio, pero ahora ya no en la zona central (cerca de Ueno), sino al noroeste, casi en la división entre la capital y la prefectura de Saitama. Y con la mudanza ya ustedes saben todo lo que viene: trámites, empacar, desempacar. Y por más que intenté hacer los primeros 2 con tiempo, a fin de cuentas me pasé el fin de semana pasado sin dormir absolutamente nada, todo por terminar de hacer las maletas, o siendo más precisos, llenar las cajas de cartón.

La nueva casa está en una zona que se asemeja mucho a Kitakyushu, en Fukuoka: muy tranquila, muchas casas, pocos comercios, y sin carro todo es más difícil. De haber sabido que estaría en un lugar como éste me habría traido el carro desde Iizuka, pero hace 6 meses jamás pensé que me mudaría de donde estaba antes, y menos tan pronto.

Tomar la decisión de salirme de la ahora casa anterior no fue fácil: hubo que tomar en cuenta muchos factores; pero el que más peso tuvo fue el de depender del trabajo actual para poder vivir ahí. Con la situación como está y los planes que se aproximan, creo que la mejor opción fue decirle adiós a esa morada. Hay recuerdos en ella, sí, pero aunque quisiera que todos fueran buenos, no lo son. Muchos podrían pensar que es normal que no todo sea color de rosa (y tienen razón), pero personalmente esa casa, y para el caso, este trabajo, representan una etapa de mi vida, tanto personal, profesional y en mi estancia en Japón, muy difícil y, sobre todo, frustrante. Para salir de eso, necesitaba nuevos aires.

Como comenté antes, ahora el centro de ocio (cuando haya tiempo) será Ikebukuro, especialmente la Sunshine 60 Street:

[youtube]http://www.youtube.com/watch?v=YAUbZjC77yM#![/youtube]

Esto no quiere decir que viva cerca de ese lugar, sino que ése es el lugar donde hago conexión con la ruta que me lleva a mi nuevo refugio.

Sin embargo, lo más importante para mí, y que es mucho más grande que vivir cerca de Akihabara, o para el caso del área central de la capital de este país, es lo que viene. Estoy en un momento en donde tengo que tener mucha paciencia. He perfeccionado el arte del tatemae hasta límites que no creía posibles en mí, pero todo sea por llevar la fiesta en paz. En cuando haya oportunidad, daré el brinco (léase: adiós trabajo).

Eso sí: debo darme tiempo para desempacar, porque en serio que apenas puedo pasar al entrar a la casa. Duermo rodeado de varias decenas de cajas de cartón :S