Consejos para jugar golf en PowerShell

45

¿Qué consejos generales tiene para jugar al golf en Windows PowerShell? Estoy buscando ideas que puedan aplicarse a los problemas de golf de código en general que sean al menos algo específicos de PowerShell (por ejemplo, "eliminar comentarios" no es una respuesta). Por favor, publique un consejo por respuesta.

Tomado casi al pie de la letra de la pregunta de Marcog .

Joey
fuente
3
Cuando busqué en Google "PowerShell golf", ¡este fue el primer éxito!
Matt

Respuestas:

24

Potencias de 10 literales con notación científica:

4e6 = 4000000

Poderes de 2 literales:

4KB = 4096
4MB = 4194304
4GB = 4294967296

# TB and PB suffixes also exist, but less useful for golf.

Podría ser útil.

Joey
fuente
19

Si necesita ejecutar un bucle y sabe exactamente cuántas veces necesita ejecutarse cada vez, considere conectar una matriz de enteros contiguos a ForEach-Objecttravés del %alias en lugar de usar for.

for($x=1;$x-le10;$x++){...}

vs

1..10|%{...}

Iszi
fuente
18

Puede omitir muchos espacios en PowerShell. Si parece que podría no ser necesario, posiblemente no lo sea. Esto es particularmente útil en las comparaciones.

Ejemplo:

$x-eq$i-and$x-ne9

vs.

$x -eq $i -and $x -ne 9

Si necesita bifurcar su script en función del resultado de una sola prueba que puede tener múltiples resultados, a switchveces puede igualar o superar una declaración if.

Ejemplo (cambio vs. if / else - empate):

if($x%2-eq0){'even'}else{'odd'}

vs.

switch($x%2){0{'even'}1{'odd'}}

O (cambiar vs if / elseif / else - cambiar gana por 15):

if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}

vs.

switch($x%2){0{'even'}1{'odd'}2{'error'}}

Si el interruptor se basa realmente en ciertos resultados matemáticos, como la operación de módulo anterior, puede reemplazar el interruptor por completo con una matriz. Aquí, guarda otros 13 caracteres y es incluso más corto que la declaración original de dos opciones if / else. (Gracias a Danko Durbic por esta parte).

('even','odd','error')[$x%2]

Si va a utilizar mucho un comando en particular, especialmente uno sin un alias de mano corta preexistente, configure un alias de un solo carácter desde el principio.

Ejemplo:

nal g Get-Random;g 10;g 10;g 10

vs.

Get-Random 10;Get-Random 10;Get-Random 10
Iszi
fuente
('even','odd')[$x%2]FYI.
TheIncorrigible1
15

Encapsular el comando que define una variable entre paréntesis le permite alimentar la definición de la variable directamente a otros comandos.

Por ejemplo, puede establecer $ x y luego establecer $ y en función del valor de $ x en una sola toma con esto:

$y=($x=1)+1

En lugar de esto:

$x=1;$y=$x+1

Puede configurar $ h y generarlo con esto:

($h='Hello World!')

En lugar de esto:

$h='Hello World!';$h
Iszi
fuente
1
Esto es especialmente útil para invocar métodos en objetos. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD
14

Un interruptor puede actuar como un bucle, cuando se le da una matriz. Por ejemplo:

$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
    'a'{'FOO'}
    'b'{'BAR'}
    default{'MEH'}
}

Saldrá:

FOO
BAR
MEH

No estoy totalmente seguro de dónde será útil, pero espero que sea útil para alguien en algún momento.

Iszi
fuente
2
Es útil cada vez que necesita un ForEach-Objecty un switchdentro de eso. Es, por ejemplo, un código (en el mundo real) muy bueno para escribir analizadores rápidos de archivos de texto en los que debe hacer cosas diferentes dependiendo de la expresión regular de una línea.
Joey
Esto es ... malditamente raro. Una matriz no debe coincidir con un carácter, pero sí.
gato
@Joey Para eso switch -File $pathes
TheIncorrigible1
No todo lo que se analiza es un archivo.
Joey
12

Reemplazar [math]::powcon multiplicación. En lugar de

[math]::pow($a,$b)

puedes escribir

"$a*"*$b+1|iex

Esto funciona para exponentes enteros> = 0.

Danko Durbić
fuente
Necesitaba ver esta respuesta para entender iex... Alias ​​paraInvoke-Expression
HeatfanJohn
11

Los operadores de comparación trabajan en colecciones de valores devolviendo valores coincidentes:

1..5 -gt 2

cederá 3, 4y 5. En algunos casos, esto puede ayudar a ahorrar un tiempo más largo |?{$_...}.

-match es un operador de comparación también.

Joey
fuente
1
Tenga en cuenta que no necesita espacios en ese ejemplo1..5-gt2
Matt
1
Lo sé; se trataba más de mostrar la técnica. Los espacios están en una respuesta separada .
Joey
11

Use alias siempre que sea posible. Hay un montón de útiles:

?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression
Joey
fuente
11

¿Quiere encontrar el máximo o mínimo de una colección de valores? Intentó

(...|measure -ma).Maximum

o

(...|measure -mi).Minimum

¿ya?

Simplemente ordene y use el último o primer elemento:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
Joey
fuente
1
Y, si conoce la longitud de la colección de valores y es inferior a 10 ...
wizzwizz4
@ wizzwizz4: Oh, las longitudes máximas a menudo se pueden emplear creativamente, no necesariamente siendo 10. Aunque para este caso en particular no recuerdo una instancia en la que alguna vez haya ayudado.
Joey
1
Es decir, si el último punto es conocido por ser 0, 1, 2, 3, 4, 5, 6, 7, 8o 9, se ahorraría un byte para escribir la longitud conocida en lugar de -1.
wizzwizz4
10

Acortar nombres de propiedad

Lamentablemente, a diferencia de los parámetros, las propiedades / métodos (todo lo que se accede con un punto .) no se pueden acortar a su forma inequívoca.

Pero ciertos cmdlets pueden operar con nombres de propiedad y tomar comodines, y hay conjuntos de parámetros poco conocidos %y ?que pueden ser útiles.

Por lo general, pasamos un bloque de script y nos referimos al elemento con $_, pero hay otra forma de estos que toma un nombre de propiedad y acepta un comodín.

$o|select Le*  
$o|%{$_.Length}

Con una propiedad como .Lengthno podemos usar la magia v3 que normalmente funcionaría en una matriz porque Lengthes una propiedad de la matriz en sí misma, por lo que las dos anteriores podrían usarse para obtener las longitudes de los miembros individuales. El selectviene en un poco más corto.

Pero %puede tomar un nombre de propiedad directamente y devolver ese valor:

$a|% Length

Que se puede acortar con comodines. El comodín debe resolverse en una sola propiedad (o método, más sobre eso más adelante), por lo que arrojará un error útil si no lo hace, indicando exactamente a qué miembros podría resolver.

En el caso de Length, Le*suele ser el más corto. Incluso en una sola cadena, este método es 1 byte más corto que simplemente usar la propiedad.

$a.Length                # 9   #(doesn't work on array)
$a|%{$_.Length}          # 15
$a|% Le*                 # 8

Pero dependiendo de lo que esté haciendo con esto, esto puede ser peor. Puede hacerlo, $a.Length*5pero para hacerlo con la expresión de canalización, tendría que ajustarlo ($a|% Le*)*5; aún podría valer la pena si está en contra de una matriz, pero el punto es que no siempre es apropiado como una sustitución directa.

También funciona con métodos, y puede omitir el ()que hace que un nombre completo tenga la misma longitud, pero la misma restricción que antes, sobre a veces tener que envolverlo. El método debe tener una sobrecarga que no tome parámetros (puede pasar argumentos colocándolos después del nombre del método, lo cual es realmente bueno):

$a.ToUpper()             # 12
$a|% *per                #  9

Con argumentos:

'gaga'-replace'g','r'    # 21
'gaga'|% *ce g r         # 16

Estos no son estrictamente iguales en el sentido de que el -replaceoperador hace un reemplazo de expresiones regulares, pero si solo está haciendo un reemplazo de cadena, puede (ahora) ser más corto para usar el método; ayuda que las cadenas sean argumentos de cmdlet en lugar de argumentos de método, por lo que no es necesario citarlas.

Propiedades del objeto donde

?también puede tomar nombres de propiedades (parciales) y aplicarle un "operador" (en forma de parámetros de cambio). Nuevamente, esto puede ser más corto que usar el Where-Objectenfoque estándar de bloque de script si el nombre de la propiedad es lo suficientemente largo y único.

$a|?{$_.Length-gt5}      # 19
$a|? Le* -GT 5           # 14

($a|% Le*)-gt5           # 14 - Lengths, not objs
briantista
fuente
1
Uno de los pocos lugares donde se requiere espacio en blanco. Buen hallazgo, sin embargo. Puedo pensar en varias áreas donde esto acortará las cosas.
AdmBorkBork
Buena edición Joey! Gracias.
briantist
Te encontré una forma de acortarlo ;-) ... lo triste de esto es que, en general, es una tubería nuevamente, lo que limita un poco su utilidad. O, más bien, hay muchos lugares donde tendrías que ponerlo entre paréntesis nuevamente para obtener una expresión. Pero pocas técnicas de golf son sin compensaciones ...
Joey
1
@ConnorLSW ah, sí, tenía la intención de actualizar esto, ya que me di cuenta de que puede pasar argumentos de esa manera, lo que aumenta enormemente su utilidad. Gran uso de .ToString()!
briantist
2
@briantist esto ha convertido a PowerShell en un lenguaje mucho más competitivo, realmente elimina algunas de las llamadas .Net molestas y detalladas.
colsw
9

Encontrar una suma a lo largo del camino:

(...|measure -s).Sum

Un camino más corto:

...|%{$s+=$_};$s

Y aún más corto:

...-join'+'|iex
Joey
fuente
9

Los punto y coma y los saltos de línea son intercambiables. El código de golf es a menudo más legible si no se atasca en una sola línea. Y la longitud sigue siendo la misma (siempre que use U + 000A como salto de línea que PowerShell maneja sin problemas).

Joey
fuente
2
Espera, ¿estamos preocupados por la legibilidad?
Kevin Cox
44
Si no tiene ningún efecto sobre la longitud ... ¿por qué no?
Joey
¿Técnicamente no hace una diferencia ya que un punto y coma es un carácter menos que \ r \ n? Solo en Unix es un singular \ n.
Vasili Syrakis
2
@Vasili: puede guardar los archivos perfectamente con solo U + 000A entre líneas. PowerShell no se quejará. Lo cual ya escribí en la respuesta, por cierto. Los saltos de línea son una propiedad del archivo , no del sistema operativo en el que se utiliza. Nadie dice que no puede usar finales de línea Unix en Windows.
Joey
@Joey Si ha utilizado una nueva instalación de Windows para hacer una programación rápida, notará que el Bloc de notas no funciona bien con \ x0a
Stan Strum
9

El Getverbo está implícito. Esto puede acortar cualquiera Get-Froba solo Frob. Los contendientes frecuentes son dateo random.

Tenga en cuenta que esto no funcionará correctamente en algunos casos porque puede tener utilidades GNU en su camino (u otros programas nativos que entren en conflicto). La búsqueda de orden de comando en ese caso parece preferir el programa nativo antes de considerar cmdlets con el Get-eliminado:

PS Home:\> date

Freitag, 15. November 2013 07:13:45


PS Home:\> $Env:Path += ';D:\Users\Joey\Apps\GnuWin32\bin'
PS Home:\> date
Fr Nov 15 07:14:13 W. Europe Standard Time 2013
Joey
fuente
Esto no significa absolutamente siempre funciona como se esperaba. Tengo un script que comienza con nal g Get-Randomguardar caracteres más adelante. Cambiarlo a nal g Randomcausa que el script se cuelgue indefinidamente (o, al menos, tome un tiempo excesivo para procesarlo; no he tenido la paciencia de esperar a que termine, pero está tomando varios órdenes de magnitud más que la forma original antes de abortar).
Iszi
2
Dos Measure-Commandinvocaciones cortas (100 veces Get-Randomvs. random) me dicen que es aproximadamente 500 veces más lento. No lo sabía antes, para ser honesto. Pero es bueno tenerlo en cuenta, especialmente en bucles con muchas iteraciones. Dicho esto, el código de golf debe ser corto, no rápido ( dicho esto, apesta tener que esperar dos días para obtener una respuesta a un problema del Proyecto Euler).
Joey
1
Mi problema era ejecutar 10,000 iteraciones del escenario Monty Hall, cada una de las cuales requería tres iteraciones de Get-Random. Un aumento del 50,000% en el tiempo de procesamiento, multiplicado en 30,000 ejecuciones es bastante desagradable.
Iszi
Guau. Parece que lo mismo probablemente sea cierto para cualquier alias. Probado Get-Variablevs. gvy obtuve una comparación similar.
Iszi
1
Eso podría ser. Hice algunos cálculos y pensé que mi script de Monty Hall debería tardar aproximadamente 1,5 horas (normalmente, 10-11 segundos) en ejecutarse sin él Get-. Esa es una hinchazón bastante retorcida en el tiempo de ejecución para un ahorro de solo 4 caracteres de longitud.
Iszi
8

for los bucles pueden tener entre 0 y tres declaraciones en su encabezado:

Ciclo infinito:

for(){}

Bucle con inicialización:

for($n=0){}

Bucle con inicialización y condición final:

for($n=0;$n-lt7){}

En tales casos, se pueden omitir los puntos y comas adicionales al final (se indica explícitamente en la especificación del lenguaje , por lo que no es un detalle de implementación) en contraste con los lenguajes tipo C que siempre requieren exactamente tres declaraciones.

Esto también hace whileun poco más corto. Comparar

while(...){}

y

for(;...){}

Con la bonificación adicional de que puedes quedarte en una línea anterior (si hay una) en el fortambién sin costo adicional (e incluso guardar un personaje).

Joey
fuente
8

Si está asignando una matriz que sabe que solo tendrá dos valores, no use la indexación.

Algo como esto:

$a="apple","orange"
$a[0] # apple
$a[1] # orange

Se puede convertir fácilmente en esto:

$a,$o="apple","orange"
$a # apple
$o # orange

Esto también puede ser útil si solo necesita el primer elemento de una matriz:

$a,$b=1..10
$a # 1
$b # 2..10
SomeShinyMonica
fuente
En este caso (con las cadenas) $a="apple";$o="orange"es idéntico en longitud. Son las matrices más largas las que a veces se pueden optimizar bastante bien, por ejemplo, colocando todos los elementos en una cadena con un separador y luego usando -split(lo mejor es usar espacios en blanco como separador porque entonces el unario -splitserá suficiente).
Joey
8

Fundición a cuerda:

[string]$x

vs.

"$x"

La conversión a una cadena como esta también se puede usar para aplanar una serie de cadenas, en lugar de unirla:

$a = @('a','b','c')
$a -join ' '

vs.

$a = @('a','b','c')
"$a"

Transmitir una cadena a un tipo numérico:

[int]$x     [float]$x

vs.

+$x

También es muy útil saber que PowerShell siempre toma el tipo del operando izquierdo para determinar el tipo final de una expresión y las conversiones a aplicar:

'1'+2    -> '12'
1+'2'    -> 3

lo que puede ayudar a determinar dónde están los moldes innecesarios.

Joey
fuente
6

No olvide que no siempre necesita proporcionar el nombre completo de un parámetro, y algunos parámetros son posicionales.

Get-Random -InputObject (0..10)

... se puede recortar para ...

Get-Random -I (0..10)

... porque "I", en este caso, es suficiente para identificar de manera única InputObjectlos otros parámetros válidos para este comando.

Podrías recortarlo aún más para ...

Get-Random (0..10)

... porque InputObjectes un parámetro posicional.

La tubería suele ser más corta que alimentar objetos como parámetro, especialmente cuando puede eliminar la necesidad de paréntesis. Recortemos más nuestro generador de números aleatorios ...

0..10|Get-Random

También esté atento a otras formas de lograr lo mismo, incluso si no puede cambiar el comando. Para el caso anterior, puede hacer esto:

Get-Random 11

O, incorporando otra sugerencia *:

Random 11

** Nota: La omisión Get-de un nombre de comando puede aumentar el tiempo de ejecución en aproximadamente un 50,000%. No está mal si solo necesita el comando una vez, pero tenga cuidado al usarlo en bucles largos. *

Y así es como puede derribar un comando simple hasta un tercio de su tamaño.

Iszi
fuente
6

Operador ternario falso. Puede asignar directamente desde una ifdeclaración:

$z=if($x-eq$y){"truth"}else{"false"}

Pero puede usar una matriz de 2 elementos y usar la prueba para indexarla. Los resultados de $ falsey obtienen el elemento 0, los resultados de $ verdadero toman el elemento 1:

$z=("false","true")[$x-eq$y]

NÓTESE BIEN. que esto realmente está haciendo indexación de matriz, y si la prueba da como resultado un valor que se puede convertir a un entero, solicitará un elemento fuera de los límites de la matriz y obtendrá $ nulo de regreso, y tendrá que hacerlo !(test)para forzar lanzar el resultado a un bool, con las opciones invertidas.

TessellatingHeckler
fuente
El primer fragmento no funcionó en un punto en el tiempo (versiones anteriores de PowerShell), si no recuerdo mal, por lo que es necesario envolverlo $(). Hubo esencialmente una distinción del uso de tuberías hechas de comandos y declaraciones como expresiones. Parece que ya no existe, al menos en PowerShell 5.
Joey
Además, si los elementos de la matriz no son estáticos, ambos se analizan y procesan como parte de la creación de la matriz antes de que ocurra la indexación y se asigne el resultado. Por ejemplo .
AdmBorkBork
6

Cuando use un número como argumento para un operador que de otra manera requeriría una cadena, puede usar el número directamente. Comparar

...-join'0'

vs.

...-join0

Funciona con -splittambién. El argumento siempre se convierte primero en una cadena.

Joey
fuente
Como referencia, esto también funciona -replace.
AdmBorkBork
-replacetambién funciona sin un segundo argumento cuando quiera eliminar coincidencias,
Joey
5

Valor absoluto

Con

$n=-123

En lugar de

[math]::abs($n)

utilizar

$n-replace'-'

Por supuesto, los ahorros se cancelan si se necesitan paréntesis.

Rynant
fuente
O si necesita el resultado en el lado izquierdo de un operador ;-)
Joey
5

Si necesita silenciar los errores, la variante obvia sería

try{ <# something that throws errors #> }catch{}

Sin embargo, esto es demasiado largo. Una variante más corta es ejecutar el trybloque como un bloque de script y simplemente redirigir los errores a una variable no establecida ( $nullsería la habitual, pero aún es demasiado larga):

.{ <# something that throws errors #> }2>$x

Esto ahorra cinco bytes valiosos (si no el mundo).

Joey
fuente
5

Utilice la $ofs variable especial para cambiar el O utput F ield S eparator utilizado cuando stringifying una matriz. Útil si necesita transformar matrices en cadenas varias veces.

Por ejemplo:

$a=1,2,3,4
$a-join',';$a-join','
$ofs=',';"$a";"$a"

Guarda 2+ n caracteres en el 2do -join, donde n es la longitud del separador, y guarda 5+ n adicionales para el 3ro -joiny cada uno a partir de entonces.

AdmBorkBork
fuente
1
Lamentablemente, rara vez es útil (al menos en mi golf hasta ahora, tiendo a reducirlo a una sola unión al final).
Joey
5

Las variables automáticas tienen booleanos para Verdadero y Falso como $truey, $falsepero puede obtener resultados similares utilizando el operador lógico no !y los enteros 0 y 1 (o cualquier entero distinto de cero).

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Casi todas las expresiones de PowerShell se pueden evaluar como booleanos. Por lo tanto, siempre que sepa cómo se evalúan ciertos datos, puede obtener booleanos y nunca necesitará emitirlos explícitamente. Tenga en cuenta el valor de LHS al hacer esto.

  • El entero 0 es falso y los enteros distintos de cero se evalúan como verdaderos.
  • las cadenas de longitud distinta de cero son verdaderas y las cadenas vacías o nulas (y las nulas mismas) son falsas.

Hay otros ejemplos, pero puedes probarlos fácilmente haciendo un reparto

PS C:\Users\matt> [bool]@(0)
False
Mate
fuente
1
Muchos otros tipos de datos también tienen un estado similar. Las variables no inicializadas son, por defecto $null, falsey. La cadena vacía (y las variables establecidas en la cadena vacía) son falsey. Etc. Esto se puede usar para atajar la indexación en una matriz (por ejemplo, al hacer un if/ else), como se usó en FizzBuzz .
AdmBorkBork
@TimmyD Muy cierto. Usar ints es más corto
Matt
@TimmyD Quería responder a fizzbuzz hasta que vi el tuyo ... No puedo vencer eso ... al menos todavía no
Matt
Tenga en cuenta que en muchos casos en realidad no necesita a bool. Puedes usar 0y 1igual de bien. Las conversiones implícitas ayudan mucho en ese sentido (que a menudo puede forzar con ciertos operadores).
Joey
4

Invoke-Expressiony Get-Randomtambién puede obtener entradas de canalización en lugar de argumentos.

Para iexesto permite guardar paréntesis en algunas expresiones:

iex 1..5-join'+'   # won't work
iex(1..5-join'+')  # does work, but has extra parentheses
1..5-join'+'|iex   # doesn't need the parentheses

En caso de que randomesto permita que un caso común se optimice un poco:

random -mi 10 31   # gets a random integer between 10 and 30
10..30|random      # much better :-)
(random 21)+10     # if needed in another expression that doesn't require extra
                   # parentheses

La última forma de usarlo simplemente selecciona un elemento de una lista. Se -cpuede dar el argumento para permitir más de una sola selección.

Joey
fuente
4

Considere almacenar bloques de script repetidos en variables, en lugar de usar funciones.

Iba a usar esto para guardar algunos caracteres en mi implementación de Piedra, Papel, Tijera antes de darme cuenta de que reescribir la función como una variable hacía innecesaria incluso la variable. Sin embargo, esto podría ser útil para otras secuencias de comandos, donde realmente está ejecutando el mismo código varias veces.

function Hi{echo 'Hello, World!'};Hi

vs.

$Hi={echo 'Hello, World!'};&$Hi
Iszi
fuente
2
Útil para funciones que no toman argumentos. De lo contrario params(...), ocuparía más espacio del que guarda la definición de función. Relacionado: Uso filtersobre functioncuándo puede hacerlo.
Joey
Puede utilizar $argspara evitar la necesidad de params; es decir $x={$args[0]+2}(o incluso $x={2+"$args"}); puede guardar un personaje o 2 en algunas circunstancias. También puede combinar esto con otro truco para múltiples parámetros:$x={$a,$b=$args;$a+$b+3}
JohnLBevan
4

En su $s|% t*ylugar, puede usar [char[]]$spara dividir una cadena en una matriz de caracteres. Dado de la respuesta de TessellatingHeckler : se % t*yexpande a | ForEach-Object -Method ToCharArrayequiv. de"$args".ToCharArray()

Por ejemplo, compare

$s|% t*y

y

[char[]]$s

y

$s.ToCharArray()

Es útil $argsespecialmente con :$args|% t*y

mazzy
fuente
1
Eso es bastante bueno. También he usado el %truco para miembros varias veces, pero la mayoría de mis juegos de golf son anteriores a esa característica ;-). También es una técnica bastante general: intente encontrar una combinación de letra / comodín que coincida con la propiedad / método que necesita (y es más corta que la real).
Joey
Otros ejemplos útiles de la respuesta: $s|% *perpor $s.toUpper()y $s|% *werpara $s.toLower(). Estoy de acuerdo en que es bastante bueno.
mazzy
Un ejemplo más : |% t* "ddd\:hh\:mm\:ss"para[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy
Bueno, eso es solo un desperdicio de citas, entonces; no los necesitas aquí :-)
Joey
3

Utilice la lógica booleana en lugar de los contadores de if en un bucle

Supongamos que está agregando todos los números pares del 1 al 10 ... 2+4+6+8+10=30

1..10|%{if($_%2-eq0){$o+=$_}};$o

Podría usar la negación booleana para acortarla a

1..10|%{if(!($_%2)){$o+=$_}};$o

para guardar un byte, pero ¿qué tal si en su lugar utiliza la conversión implícita de booleanos a ints y pasa el condicional al acumulador?

1..10|%{$o+=$_*!($_%2)};$o

Guarda 6 bytes en este ejemplo.

AdmBorkBork
fuente
2
Jesucristo. Estoy planeando hacer esto en mi código de producción en el trabajo, mis colegas me amarán por ello.
Chávez el
3

La conversión de números de punto flotante a enteros en PowerShell es un poco un campo minado. Por defecto, la conversión realiza redondeo de los banqueros, que no siempre recorta el decimal y deja el número entero más pequeño, o siempre redondea .5 al siguiente número, como lo hace la gente de manera casual, redondea los pares de una manera y las probabilidades de otra manera, esto puede ser sorprendente, por ejemplo

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

y romper los cálculos de codegolf. Muchos otros idiomas comunes hacen redondeo de truncamiento, por lo tanto, las preguntas de golf a menudo requieren truncamiento. Puede llegar a [Math]::Floor()ser la siguiente mejor opción, pero tenga en cuenta que esto solo se comporta igual que el truncamiento para números positivos, pero toma números negativos más bajos, más lejos de cero. [Math]::Truncate()es lo que necesita para alinear el comportamiento de PS con el redondeo predeterminado de otro idioma, pero son muchos caracteres.

Regex reemplazando dígitos después del punto decimal puede ayudar a guardar un par de caracteres:

[Math]::Truncate(1.5)
[Math]::Floor(1.5)
1.5-replace'\..*'

[Math]::Truncate($a)
[Math]::Floor($a)
$a-replace'\..*'
$a.split('.')[0]        # literal character split, not regex pattern split
TessellatingHeckler
fuente
3

Invertir una matriz

Resulta útil en muchos desafíos de donde la producción se refleja de alguna manera.

Supongamos que tienes

$a=1,2,3,4,5

El método de inversión tradicional es largo, aburrido y no deja la matriz en la tubería para su uso inmediato.

[array]::reverse($a)

La indexación directamente en la matriz en orden inverso ahorra algunos bytes, ya que deja los resultados en la tubería, pero aún es bastante largo:

$a[($a.count-1)..0]

En cambio, intente un bucle

$a|%{$a[-++$i]}
AdmBorkBork
fuente
la indexación inversa funciona bien cuando hay un límite superior para el recuento
Joey
3

A partir de PowerShell Core 6, también puede usar rangos para caracteres:

'a'..'z'

que puede reemplazar a los mucho más engorrosos

0..25|%{[char]($_+97)}
Joey
fuente
Oh, esto va a ser muy útil.
AdmBorkBork
1
[char[]](65..90)también es una forma práctica de generar el alfabeto
Veskah