Mathematica, 72 65 61 bytes
Print@@@Tuples@{a=##/(b=#5#9#15#21#25#)&@@Alphabet[],b,a,b,a}
Para las pruebas, recomiendo reemplazarlas Print@@@
por ""<>#&/@
. Luego, Mathematica mostrará un formulario truncado que muestra las primeras y últimas palabras, en lugar de tomar una eternidad para imprimir 288,000 líneas.
Explicación
Finalmente encontré un uso para dividir cadenas. :)
Me ha intrigado la posibilidad de agregar o multiplicar cadenas por un tiempo, pero los casos de uso reales son bastante limitados. El punto principal es que algo como "foo"+"bar"
o "foo"*"bar"
(y, en consecuencia, la forma abreviada "foo""bar"
) es completamente válido en Mathematica. Sin embargo, realmente no sabe qué hacer con las cadenas en las expresiones aritméticas, por lo que estas cosas permanecen sin evaluar. Sin embargo, Mathematica aplica simplificaciones generalmente aplicables. En particular, las cadenas se ordenarán en orden canónico (que está bastante desordenado en Mathematica, una vez que comience a ordenar cadenas que contienen letras de varios casos, dígitos y no letras), que a menudo es un factor decisivo, pero no importa aquí . Además, "abc""abc"
se simplificará a"abc"^2
(lo cual es un problema cuando tiene cadenas repetidas, pero tampoco tenemos eso), y algo así "abc"/"abc"
se cancelará (que incluso haremos uso de).
Entonces, ¿qué estamos tratando de jugar golf aquí? Necesitamos una lista de vocales y una lista de consonantes, de modo que podamos alimentarlas Tuples
para generar todas las combinaciones posibles. Mi primer enfoque fue la solución ingenua:
Characters@{a="bcdfghjklmnpqrstvwxz",b="aeiouy",a,b,a}
Esa lista codificada de consonantes duele un poco. Mathematica tiene una función Alphabet
incorporada que me permitiría evitarlo, si pudiera eliminar las vocales de una manera barata. Sin embargo, aquí es donde se pone difícil. La forma más sencilla de eliminar elementos es Complement
, pero eso termina siendo más largo, utilizando una de las siguientes opciones:
{a=Complement[Alphabet[],b=Characters@"aeiouy"],b,a,b,a}
{a=Complement[x=Alphabet[],b=x[[{1,5,9,15,21,25}]]],b,a,b,a}
(Tenga en cuenta que ya no necesitamos aplicar Characters
a todo el asunto, porque Alphabet[]
da una lista de letras, no una cadena).
Así que intentemos ese negocio aritmético. Si representamos el alfabeto completo como un producto de letras en lugar de una lista, entonces podemos eliminar letras por división simple, debido a la regla de cancelación. Eso ahorra muchos bytes porque no los necesitaremos Complement
. Además, en "a""e""i""o""u""y"
realidad es un byte más corto que Characters@"aeiouy"
. Entonces hacemos esto con:
a=##/(b="a""e""i""o""u""y")&@@Alphabet[]
Donde estamos almacenando los productos de consonantes y vocales en a
y b
, respectivamente. Esto funciona escribiendo una función que multiplica todos sus argumentos ##
y los divide por el producto de las vocales. Esta función se aplica a la lista del alfabeto, que pasa cada letra como un argumento separado.
Hasta ahora todo bien, pero ahora tenemos
{a=##/(b="a""e""i""o""u""y")&@@Alphabet[],b,a,b,a}
como argumento para Tuples
, y esas cosas siguen siendo productos, no listas. Normalmente, la forma más rápida de arreglar eso es poner un List@@@
al frente, lo que convierte los productos en listas nuevamente. Desafortunadamente, agregar esos 7 bytes lo hace más largo que el enfoque ingenuo.
Sin embargo, resulta que Tuples
no le importan en absoluto los encabezados de las listas internas. Si lo haces
Tuples[{f[1, 2], f[3, 4]}]
(Sí, para un indefinido f
). Obtendrá:
{{1, 3}, {1, 4}, {2, 3}, {2, 4}}
Como si hubieras usado un en List
lugar de f
. Por lo tanto, podemos pasar esos productos directamente Tuples
y aún así obtener el resultado correcto. Esto ahorra 5 bytes sobre el enfoque ingenuo utilizando dos cadenas codificadas.
Ahora el "a""e""i""o""u""y"
sigue siendo bastante molesto. Pero espera, ¡también podemos guardar algunos bytes aquí! Los argumentos de nuestra función son las letras individuales. Entonces, si solo seleccionamos los argumentos correctos, podemos reutilizarlos en lugar de los literales de cadena, que es más corto para tres de ellos. Queremos argumentos#
(abreviatura de #1
), #5
, #9
, #15
, #21
y #25
. Si lo ponemos #
al final, tampoco necesitamos agregar ninguno *
para multiplicarlos, porque (regex) #\d+
es un token completo que no puede tener ningún dígito agregado. Por lo tanto, terminamos #5#9#15#21#25#
ahorrando otros 4 bytes.