Consejos para jugar golf en MATL

20

MATL es un lenguaje de golf creado por Luis Mendo . MATL ha demostrado ser altamente competitivo, a menudo superando las presentaciones en otros idiomas de golf como Pyth, CJam y Jelly.

¿Cuáles son algunos consejos útiles para jugar golf en MATL? (Como siempre, un consejo por respuesta, ¡por favor!)

Stewie Griffin
fuente
55
Definitivamente es una gran ventaja si conoces algo de Matlab / Octave. Algunos trucos de Consejos para jugar golf en Matlab y Consejos para jugar golf en Octave también se usan en MATL.
flawr
Sugerencia: parece que accumarray( XQ) puede ser bastante potente (posiblemente incluso más que en MATLAB / Octave, ya que esos controladores de función de longitud tienen códigos numéricos útiles), pero no lo sé lo suficientemente bien como para ilustrar con buenos ejemplos. Si realmente es útil, ¿alguien podría crear una respuesta con ideas sobre cómo usarla?
sundar - Restablecer Monica

Respuestas:

7

Conoce los literales predefinidos

Aunque algunos de ellos guardan información cuando se copian en el portapapeles, todos tienen un valor predefinido.

  • F, empuja 0 (en realidad falso )
  • T, empuja 1 (realmente cierto )
  • H, empuja 2 (valor del portapapeles predefinido)
  • I, empuja 3 (valor del portapapeles predefinido)
  • K, empuja 4 (valor del portapapeles predefinido)
  • J, empuja 0 + 1j (valor del portapapeles predefinido)

Sin embargo, no estoy seguro de si he cubierto todos los valores predefinidos.

Adnan
fuente
Solo para completar (y en caso de que desee agregar a su respuesta): cada nivel del portapapeles Ltambién tiene un valor predefinido, pero están destinados a usos especiales (en lugar de valores generales comunes). Por ejemplo, 1Lgive [1 0](que se usa como índice 1:end), 2Lgive [0 -1 1](para 1:-1:end). Además, funciona ly Otoma 0 entradas por defecto y produce 0y 1respectivamente
Luis Mendo
No veo cómo esto es útil ... ¿No puedo escribir 4?
Cyoce
@Cyoce La utilidad es evitar un espacio como separador. Si quieres empujar 1, entonces 4, 14no lo harás. Se necesitaría 1 4. O 1Kpara guardar un byte
Luis Mendo
@LuisMendo ah, ya veo. Supongo que supuse que estaba usando el método de un solo número de 1 dígito (no estoy seguro de por qué)
Cyoce
1
Otro caso cuando en Klugar de 4es útil es: 1-4significa: empujar 1, luego empujar -4; mientras que 1-Ksignifica: empujar 1, restar de lo que esté debajo en la pila, luego empujar4
Luis Mendo
5

La &metafunción (especificación alternativa de entrada / salida)

La forma tradicional de especificar el número de argumentos de entrada para pasar a una función es usar la $metafunción

2$:     % Two-input version of :

Del mismo modo, para especificar el número de argumentos de salida, puede usar la #metafunción que especifica el número de argumentos de salida,

2#S     % Two-output version of sort

o si pasa un número que es mayor que el número de argumentos de salida definidos para una función, solomod(N, numberOfOutputs) + 1 se proporciona el resultado.

4#S     % Get only the second output of sort

También puede especificar una matriz lógica como entrada #para recuperar solo argumentos de salida específicos.

TFT#u   % Three output version of unique and discard the second output

Todas estas especificaciones de entrada / salida son útiles, pero aumentan su recuento de bytes muy rápidamente. Para lidiar con esto, MATL introdujo &la metafunción en la versión 17.0.0 . Esta &metafunción actúa como un acceso directo para una especificación de entrada o salida particular para una función. Veamos qué significa eso.

En nuestro ejemplo anterior, queríamos usar la versión de dos entradas de :(crea un vector de valores equidistantes). Si bien el número predeterminado de argumentos de entrada :es 1(crea una matriz a partir de [1...N]), es muy común que un usuario desee especificar el valor inicial del rango que requiere la segunda entrada. Entonces :, hemos definido &como un atajo para 2$.

10      % Push 10 to the stack
12      % Push 12 to the stack
2$:     % Create an array: [10, 11, 12] 

Ahora se convierte en lo siguiente, ¡ guardando un byte !

10 12 &:

¿Cómo podemos determinar cuál es el número alternativo de argumentos?

La especificación de entrada / salida a la que se &traduce es específica de la función, de modo que optimizamos el ahorro de bytes.

La sección de argumento de entrada / salida de la descripción de ayuda para cada función se ha actualizado para indicar cuál es este número alternativo de entradas / salidas (si corresponde). El número posible de argumentos de entrada o salida se muestra como un rango y los valores predeterminados para cada uno se muestran entre paréntesis. La especificación de entrada / salida con la que se puede sustituir &se muestra después del /carácter entre paréntesis.

Aquí está la sección de argumento de entrada / salida de la descripción de ayuda para :

 +- Min-Max range of # of inputs
 |        +----- Alt. Default # of inputs
 |        |
 V        V
1--3 (1 / 2); 1 <--- Possible / Default # of outputs
      ^       
      |       
  Default # of inputs

¿Cómo determinó qué &significa para cada función?

Muy cuidadosamente. Usando la API StackExchange , pudimos descargar todas las respuestas MATL que alguna vez se utilizaron en un desafío PPCG. Al analizar cada una de las respuestas, pudimos determinar la frecuencia con la que se utilizó cada especificación de entrada / salida para cada función. Con esta información, pudimos identificar objetivamente la especificación de entrada / salida que la &metafunción debería representar para cada función. A veces no había un ganador claro, por lo que muchas funciones actualmente no se han &definido.

Aquí está el script que usamos (desafortunadamente está escrito en MATLAB y no en MATL).

Y aquí hay un ejemplo del histograma de $/ #uso

Suever
fuente
1
Esta característica fue sugerida por @Suever. Originalmente &iba a significar "aumentar el número de entradas en 1 con respecto al valor predeterminado". Su sugerencia resultó ser mucho más útil
Luis Mendo
5

Familiarícese con las definiciones de verdad / falsedad de MATL

Mientras que true( T) y false( F) representan claramente la salida de verdad y falsedad, respectivamente, la definición ampliamente acordada de verdad / falsedad nos da un poco más de flexibilidad en MATL.

La definición dice:

if (x)
    disp("x is truthy");
else
    disp("x is falsy");
end

Por lo tanto, podemos escribir una prueba MATL verdadero / falso que pasará por todas las entradas y mostrará si se consideraron verdaderas o falsas

` ? 'truthy' } 'falsey' ]DT

Aquí hay una versión en línea.

Lo que esto significa en MATL

En realidad, esto se traduce en MATL (y, por lo tanto, en MATLAB y Octave) es que una condición se considera verdadera si no está vacía y los componentes reales de todos sus valores no son cero . Hay dos partes en esto que deben enfatizarse.

  1. No cero : Esto significa precisamente eso, no igual a cero ( ==). Esto incluye números positivos, números negativos, caracteres no nulos, etc. Puede verificar fácilmente convirtiendo un valor dado en un logicalvalor ( g) o puede usar~~

    F           % Falsy
    T           % Truthy
    0           % Falsy
    1           % Truthy
    2           % Truthy
    -1          % Truthy
    'a'         % Truthy
    ' '         % Truthy (ASCII 32)
    char(0)     % Falsy  (ASCII 0)  
    
  2. Todos los valores : normalmente pensamos que los escalares son verdaderos o falsos, pero en MATL, podemos evaluar escalares, vectores de fila, vectores de columna o incluso matrices multidimensionales y se consideran verdaderos si y solo si cada valor es no es cero (como se definió anteriormente), de lo contrario son falsos. Aquí hay algunos ejemplos para demostrar

    [1, 1, 1]           % Truthy
    [1, 0, 0]           % Falsey
    [1, 1, 1; 1, 1, 1]  % Truthy
    [1, 0, 1; 1, 1, 1]  % Falsey
    'Hello World'       % Truthy
    

El caso de un borde, como se mencionó anteriormente, es una matriz vacía [], que siempre se considera falsa ( ejemplo )

¿Cómo puedo usar esto para jugar mejor al golf?

Si el desafío simplemente menciona que su salida debe ser verdadera o falsa, es probable que pueda explotar la definición anterior para reducir algunos bytes de su respuesta. Para evitar confusiones, se recomienda que incluya un enlace a la prueba de verdad / falsedad en línea en su respuesta para ayudar a explicar cómo funcionan los valores de verdad / falsedad de MATL.

Un par de ejemplos específicos:

  • Una respuesta que termina en A. Si el desafío requiere una salida verdadera o falsa y finaliza su respuesta en all( A) para crear un escalar, puede eliminar este último byte y su respuesta seguirá siendo correcta (a menos que la salida sea []ya que []es falsepero []Aes true).

  • Asegurarse de que una matriz contiene solo un valor único : Usos &=en lugar de un1=. Si todos los valores en una matriz son iguales, una comparación de igualdad de elementos emitida emitirá una N x Nmatriz de todos. Si todos los valores no son iguales, esta matriz contendrá algunos 0valores y, por lo tanto, se considerará falsa.

Suever
fuente
4

Entrada implícita

La mayoría de las funciones aceptan algún número de entrada. Estas entradas se toman de la parte superior de la pila. Si la parte superior de la pila no contiene suficientes argumentos, extraerá el argumento restante de la entrada. (Consulte la Sección 7.3 de la documentación) Me gustaría citar la explicación original:

Las entradas implícitas se pueden ver de la siguiente manera: la pila se extiende indefinidamente debajo de la parte inferior, es decir, en las posiciones 0, −1, −2, ... con valores que no se definen inicialmente, pero que se resuelven sobre la marcha a través de la entrada implícita . Estas entradas se solicitan al usuario solo cuando se necesitan, en el orden en que se necesitan. Si se requieren varias entradas al mismo tiempo que siguen el orden normal de la pila, es decir, la entrada que es más profunda en la pila (extendida) se ingresa primero.

falla
fuente
2
La entrada implícita es una característica sugerida por @flawr
Luis Mendo
66
@flawr debe ser un tipo muy inteligente. : D
flawr
3

Las matrices lógicas a menudo se pueden usar como matrices numéricas

A menudo puede usar " TF" la notación en lugar de los literales de matriz de ceros y unos. Por ejemplo, FTFes lo mismo que [0,1,0], solo que FTFproduce logicalvalores, no doublevalores. Esto generalmente no es un problema, ya que cualquier operación aritmética tratará los valores lógicos como números. Por ejemplo, FTFQda [1,2,1]( Qes "aumentar en 1").

En algunos casos, la conversión de un número a binario puede ser más corta. Por ejemplo, [1,0,1], TFTy 5Bson los mismos; nuevamente con la precaución de que los dos últimos son logicalvalores.


Un caso en el que la diferencia entre TF(lógico) y [1 0](numérico) es cuando se usa como índices. Una matriz de tipo logicalutilizada como índice significa: seleccionar elementos correspondientes a T, descartar los correspondientes a F. Entonces [10 20]TF)produce 10(seleccione el primer elemento), mientras que [10 20][1 0])produce [10 20](el índice [1 0]tiene la interpretación de 1:end, es decir, elige todos los elementos de la matriz).

Luis Mendo
fuente
3

Para lazo de tamaño n-1

Considere reemplazar

tnq:"...

con

td"...

para guardar hasta un byte completo o más .

Sanchises
fuente
@Luis cierto! Pensé que uno podría necesitar el vector original que se está creando, pero eso tampoco es posible en el primer enfoque. Eliminará ese comentario.
Sanchises
Pero no necesariamente guarda 1 byte; guarda 1 o 2 dependiendo de si necesita @/ X@dentro del ciclo o no. Tal vez solo puedas decir "para guardar bytes"
Luis Mendo
3

Mover cosas desde después del ciclo hasta dentro del ciclo, para explotar el fin implícito

Las enddeclaraciones de bucle ]se pueden omitir si no hay código después de ellas. Los llena el analizador MATL implícitamente.

Por lo tanto, si puede mover las cosas desde después del ciclo hasta dentro del ciclo, puede guardar el final ].

Como ejemplo específico, el siguiente código encuentra cuántos ceros finales hay en el factorial de un número N(ver aquí ):

  • El código recorre de 1a N.
  • Para cada uno de esos números, calcula sus factores primos y determina cuántas veces 5está presente.
  • La respuesta es el número acumulado de veces que 5aparece (esto funciona porque para cada uno 5hay al menos uno 2).

La primera idea fue :"@Yf5=]vs(tenga en cuenta que hay declaraciones después del ciclo):

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
]      % End for
v      % Concatenate all vectors as a column vector
s      % Sum. Implicitly display

Como vde forma predeterminada concatena todo el contenido de la pila, se puede mover al bucle. Y como la suma es asociativa, también sse puede mover. Eso deja ]al final del código y, por lo tanto, se puede omitir :"@Yf5=vs:

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
  v    % Concatenate all vectors so far as a column vector
  s    % Sum. Inplicitly end loop and display
Luis Mendo
fuente
No sé ni un centavo de este lenguaje escrito similar a los jeroglíficos, pero tal vez reservaré una gran parte de mi tiempo para estudiarlo los próximos tres meses.
Abr001am
@ Agawa001 :-) Encontrarás que es bastante similar a Matlab. También puede preguntar o comentar aquí
Luis Mendo
3

Forma más corta de definir una matriz numérica vacía, si la pila está vacía

Para empujar una matriz numérica vacía que normalmente usa []. Sin embargo, si la pila está vacía, puede guardar un byte con v. Esta función concatena por defecto todo el contenido de la pila verticalmente, por lo que si la pila está vacía, produce la matriz vacía.

Puedes verlo en acción, por ejemplo, aquí .

Luis Mendo
fuente
2

Algunas funciones se extienden en comparación con MATLAB u Octave

Si vienes de MATLAB u Octave, encontrarás que muchas funciones de MATL son similares a las funciones en esos idiomas. Pero en algunos de ellos se ha ampliado la funcionalidad.

Como ejemplo, considere la reshapefunción de MATLAB , que en MATL corresponde e. Los fragmentos de código reshape([10 20 30 40 50 60], 2, 3)y reshape([10 20 30 40 50 60], 2, [])respectivamente significan "remodelar el vector de fila [10 20 30 40 50 60en una matriz de 2 × 3" o "en una matriz de 2 filas con tantas columnas como sea necesario". Entonces, el resultado, en ambos casos, es la matriz 2D

10    30    50
20    40    60

Algo como reshape([10 20 30 40 50 60], 2, 2)o reshape([10 20 30 40 50 60], 5, [])daría un error debido a tamaños incompatibles. Sin embargo, MATL eliminará elementos en el primer caso (¡ pruébelo en línea! ) O rellene con ceros en el segundo (¡ pruébelo en línea! ) Para producir, respectivamente,

10 30
20 40 

y

10 60
20  0
30  0
40  0
50  0

Otras funciones que tienen una funcionalidad extendida en comparación con sus contrapartes de MATLAB son (lista no exhaustiva) S( sort), Yb( strsplit), m( ismember), h( horzcat), v( vertcat), Zd( gcd), Zm( lcm), YS( circshift), YA( dec2base), ZA( base2dec), Z"( blanks)

Luis Mendo
fuente
1

Obtenga el índice del primer elemento distinto de cero, si lo hay

La ffunción proporciona los índices de todos los elementos distintos de cero de una matriz. A menudo desea el índice del primer elemento distinto de cero. Eso sería f1): aplicar fy elegir su primer elemento. Pero si la matriz original no contiene ningún valor distinto de cero, fgenerará una matriz vacía ( []), e intentar seleccionar su primer elemento dará un error.

Un requisito común y más sólido es obtener el índice del primer elemento si hay al menos uno , y de lo []contrario. Esto podría hacerse con una ifsucursal después f, pero eso es costoso en bytes. Una mejor manera es fX<, es decir, aplicar la función mínima X<a la salida de f. X<devuelve una matriz vacía cuando su entrada es una matriz vacía.

Pruébalo en línea! (Tenga en cuenta que una matriz vacía no se muestra en absoluto). O vea un ejemplo de esto en el trabajo aquí .

Luis Mendo
fuente
1

Generar un rango siempre que una matriz dada

TL; WR : use en flugar de n:si la matriz solo tiene elementos distintos de cero.


A menudo es necesario generar una matriz [1 2 ... L]donde Lestá el número de elementos de una matriz dada. La forma estándar de hacerlo es n:. Por ejemplo, el código tn:*toma un vector numérico como entrada y calcula cada entrada multiplicada por su índice.

Si se garantiza que la matriz dada solo contiene entradas distintas de cero (por ejemplo, está formada por enteros positivos o es una cadena con caracteres imprimibles), n:se puede reemplazar por f, lo que produce una matriz con los índices de las entradas distintas de cero. Entonces el código anterior se convierte tf*, lo que ahorra 1 byte.

Algunos ejemplos más elaborados: 1 , 2 , 3 .

Luis Mendo
fuente
1

Definición eficiente de literales de matriz numérica

Aquí hay algunas formas que se pueden usar para guardar bytes al definir literales de matriz numérica. Los enlaces se dan a ejemplos de respuestas que los usan. Estos se han obtenido utilizando el script de análisis creado por @Suever .

Concatenación y literales predefinidos

Para matrices con números pequeños a veces se puede utilizar de concatenación (funciones hy v), así como literales predefinidos para evitar el uso de espacios como separadores: comparar [2 4], 2 4hy 2Kh, todos los cuales definen la matriz [2 4]. Del mismo modo, 2K1vcon una pila vacía define [2; 4; 1]. Ejemplo .

Letras dentro de literales de matriz numérica

Para números ligeramente mayores, puede ahorrar espacios aprovechando el hecho de que algunas letras tienen significados numéricos dentro de los literales de matriz. Entonces, en lugar de [3 5 2 7;-4 10 12 5]que pueda usar [IAHC;dX12A]. Ejemplo .

Específicamente, dentro de los literales de matriz,

  • O, l, H I KTienen sus significados habituales 0, ...,4
  • A, ..., Emalo 5, ...,9
  • X medio 10
  • a, ... dsignifica -1, ...,-4
  • Jy Gmalo 1jy-1j
  • P medio pi
  • Y medio inf
  • Nsignifica NaN.

Cadena y diferencias consecutivas

Para números más grandes, definir una cadena y calcular sus diferencias consecutivas (con d) puede ayudar: en lugar de [20 10 35 -6]usar '!5?b\'d. Esto funciona porque dusa los puntos de código de los caracteres para calcular las diferencias. Ejemplo .

Luis Mendo
fuente