Dicas para jogar golfe no PowerShell

45

Que dicas gerais você tem para jogar golfe no Windows PowerShell? Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral que sejam pelo menos um pouco específicos do PowerShell (por exemplo, "remover comentários" não é uma resposta). Poste uma dica por resposta.

- tirado quase literalmente da pergunta de Marcog .

Joey
fonte
3
Quando pesquisei no "PowerShell golf", esse foi o primeiro sucesso!
Matt

Respostas:

24

Poderes de 10 literais com notação científica:

4e6 = 4000000

Poderes de 2 literais:

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

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

Pode ser útil.

Joey
fonte
19

Se você precisa executar um loop e sabe exatamente quantas vezes ele precisa ser executado toda vez, considere canalizar uma matriz de números inteiros contíguos ForEach-Objectpelo %alias em vez de usá-lo for.

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

vs

1..10|%{...}

Iszi
fonte
18

Você pode pular muito os espaços no PowerShell. Se parece que talvez não seja necessário, provavelmente não é. Isso é particularmente útil em comparações.

Exemplo:

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

vs.

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

Se você precisar ramificar seu script com base no resultado de um único teste que pode ter vários resultados, switchàs vezes pode corresponder ou vencer uma declaração if.

Exemplo (switch vs. if / else - tie):

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

vs.

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

Ou (alternar vs. if / elseif / else - alternar vence por 15):

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

vs.

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

Se o comutador for realmente baseado em determinados resultados matemáticos, como a operação do módulo acima, você poderá substituir o comutador inteiramente por uma matriz. Aqui, ele salva outros 13 caracteres e é ainda mais curto que a instrução if / else de duas opções original. (Agradecemos a Danko Durbic por esta parte.)

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

Se você usar muito um comando específico, especialmente um sem um apelido de mão curta pré-existente, configure um apelido de um caractere logo no início.

Exemplo:

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

vs.

Get-Random 10;Get-Random 10;Get-Random 10
Iszi
fonte
('even','odd')[$x%2]PARA SUA INFORMAÇÃO.
TheIncorrigible1
15

Encapsular o comando que define uma variável entre parênteses permite alimentar a definição da variável diretamente para outros comandos.

Por exemplo, você pode definir $ xe, em seguida, definir $ y com base no valor de $ x de uma só vez:

$y=($x=1)+1

Em vez disso:

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

Você pode definir $ h e imprimi-lo com este:

($h='Hello World!')

Em vez disso:

$h='Hello World!';$h
Iszi
fonte
1
Isso é especialmente útil para chamar métodos em objetos. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD
14

Um switch pode agir como um loop, quando recebe um array. Por exemplo:

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

Saída:

FOO
BAR
MEH

Não tenho muita certeza de onde isso será útil, mas espero que seja útil para alguém em algum momento.

Iszi
fonte
2
É útil toda vez que você precisar de um ForEach-Objecte um switchdentro dele. É, por exemplo, um código (no mundo real) muito bom para escrever analisadores rápidos de arquivos de texto, nos quais é necessário fazer coisas diferentes, dependendo de qual regex corresponde uma linha.
Joey
Isso é ... muito estranho. Uma matriz não deve corresponder a um caractere, mas sim.
gato
@Joey Isso é o que switch -File $pathé para
TheIncorrigible1
Nem tudo o que é analisado passa a ser um arquivo.
Joey
12

Substitua [math]::powpor multiplicação. Ao invés de

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

você pode escrever

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

Isso funciona para expoentes inteiros> = 0.

Danko Durbić
fonte
Eu precisava ver esta resposta para entender iex... Alias paraInvoke-Expression
HeatfanJohn
11

Operadores de comparação trabalham em coleções de valores retornando valores correspondentes:

1..5 -gt 2

vai render 3, 4e 5. Em alguns casos, isso pode ajudar a economizar um tempo maior |?{$_...}.

-match também é um operador de comparação.

Joey
fonte
1
Note que você não precisa de espaços em que exemplo1..5-gt2
Matt
1
Eu sei; isso foi mais sobre mostrar a técnica. Os espaços estão em uma resposta separada .
Joey
11

Use aliases sempre que possível. Existem vários úteis:

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

Deseja encontrar o máximo ou o mínimo de uma coleção de valores? Tentou

(...|measure -ma).Maximum

ou

(...|measure -mi).Minimum

já?

Basta classificar e usar o último ou o primeiro item:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
Joey
fonte
1
E, se você sabe o tamanho do conjunto de valores e é menos de 10 ...
wizzwizz4
@ wizzwizz4: Ah, comprimentos máximos geralmente podem ser empregados de forma criativa, não necessariamente sendo 10. Embora, neste caso em particular, não me lembre de uma instância em que isso tenha ajudado.
Joey
1
Quer dizer, se o item final é conhecido por ser 0, 1, 2, 3, 4, 5, 6, 7, 8ou 9, seria salvar um byte para escrever o comprimento conhecido em vez de -1.
precisa saber é o seguinte
10

Encurtando nomes de propriedades

Infelizmente, diferentemente dos parâmetros, propriedades / métodos (qualquer coisa acessada com um ponto .) geralmente não podem ser encurtados para sua forma inequívoca.

Porém, alguns cmdlets podem operar com nomes de propriedades e receber curingas, e há conjuntos de parâmetros pouco conhecidos %e ?que podem ser úteis.

Normalmente, passamos um scriptblock e nos referimos ao item com $_, mas há outra forma que leva o nome de uma propriedade e ele aceita um curinga.

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

Com uma propriedade como .Lengthnão podemos usar a mágica da v3 que normalmente funcionaria em uma matriz porque Lengthé uma propriedade da própria matriz, portanto, as duas acima podem ser usadas para obter os comprimentos dos membros individuais. O selectvem um pouco mais curto.

Mas %pode pegar um nome de propriedade diretamente e retornar esse valor:

$a|% Length

Que pode ser reduzido com caracteres curinga. O curinga deve ser resolvido para uma única propriedade (ou método, mais sobre isso posteriormente), para gerar um erro útil, caso contrário, indicando exatamente para quais membros ele poderia resolver.

No caso de Length, Le*normalmente é o mais curto. Mesmo em uma única sequência, esse método é 1 byte menor do que apenas usar a propriedade

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

Mas, dependendo do que você está fazendo com isso, isso pode ser pior. Você pode fazer $a.Length*5isso apenas com a expressão de pipeline que precisaria envolvê-la ($a|% Le*)*5; ainda pode valer a pena se for contra uma matriz, mas o ponto é que nem sempre é apropriado como uma substituição direta.

Também funciona com métodos, e você pode deixar de fora o ()que cria um nome completo com o mesmo comprimento, mas com a mesma restrição acima, às vezes tendo que envolvê-lo. O método deve ter uma sobrecarga que não requer parâmetros (você pode passar argumentos colocando-os após o nome do método, o que é muito bom):

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

Com argumentos:

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

Eles não são estritamente os mesmos, pois o -replaceoperador substitui uma regex, mas se você estiver apenas substituindo uma sequência, pode (agora) ser mais curto para usar o método; ajuda que as strings sejam argumentos de cmdlet em vez de argumentos de método, para que não precisem ser citadas.

Propriedades Where-Object

?também pode usar nomes de propriedade (parciais) e aplicar um "operador" a ele (na forma de parâmetros de opção). Novamente, isso pode ser mais curto do que usar a Where-Objectabordagem de scriptblock padrão se o nome da propriedade for suficientemente longo e exclusivo.

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

($a|% Le*)-gt5           # 14 - Lengths, not objs
briantist
fonte
1
Um dos poucos lugares em que espaço em branco é necessário. Boa descoberta, no entanto. Eu posso pensar em várias áreas em que isso vai encurtar as coisas.
AdmBorkBork 27/02
Bom editar Joey! Obrigado.
Briantist
Encontrei uma maneira de reduzi-lo ;-) ... o triste é que, como um todo, é um pipeline novamente, o que limita um pouco sua utilidade. Ou melhor, há muitos lugares onde você teria que colocá-lo entre parênteses novamente para obter uma expressão. Mas algumas técnicas de golfe são, sem trade-offs ...
Joey
1
@ConnorLSW ah sim, eu pretendia atualizar isso, pois desde então percebi que você pode passar argumentos dessa maneira, o que aumenta muito sua utilidade. Ótimo uso de .ToString()!
Briantist #
2
O @briantist transformou o PowerShell em uma linguagem muito mais competitiva, realmente elimina algumas das chamadas .Net irritantemente detalhadas.
colsw
9

Encontrar uma soma pelo longo caminho:

(...|measure -s).Sum

Uma maneira mais curta:

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

E ainda mais curto:

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

Ponto e vírgula e quebras de linha são intercambiáveis. Código de golfe geralmente é mais legível se não estiver preso em uma única linha. E o comprimento ainda é o mesmo (desde que você use U + 000A como quebra de linha com a qual o PowerShell lida sem problemas).

Joey
fonte
2
Espere, estamos preocupados com a legibilidade ?!
Kevin Cox
4
Se não tem efeito no comprimento ... por que não?
Joey
Tecnicamente, isso não faz diferença, já que um ponto e vírgula é um caractere a menos que \ r \ n? Somente no Unix é um \ n singular.
Vasili Syrakis
2
@ Vasili: Você pode salvar os arquivos com apenas U + 000A entre as linhas. O PowerShell não vai reclamar. Que eu já escrevi na resposta, a propósito. Quebras de linha são uma propriedade do arquivo , não do sistema operacional em que é usado. Ninguém diz que você não pode usar terminações de linha Unix no Windows.
Joey
@Joey Se você já usou uma nova instalação do Windows para fazer alguma programação rápida, você vai perceber que o bloco de notas não jogar bonito com \ x0a
Stan Strum
9

O Getverbo está implícito. Isso pode reduzir qualquer um Get-Frobpara apenas Frob. Os candidatos frequentes são dateou random.

Observe que isso não funcionará corretamente em alguns casos, porque você pode ter utilitários GNU em seu caminho (ou outros programas nativos que se chocam). A ordem de pesquisa de comando nesse caso parece preferir o programa nativo antes de considerar os cmdlets com os Get-removidos:

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
fonte
Isto não bastante sempre funcionam como esperado. Eu tenho um script que começa com nal g Get-Randompara salvar os caracteres mais tarde. Mudá-lo para fazer nal g Randomcom que o script seja interrompido indefinidamente (ou, pelo menos, leva uma quantidade excessiva de tempo para processar - não tive a paciência de esperar que ele terminasse, mas está levando várias ordens de magnitude mais longas que a forma original antes de eu abortar).
Iszi
2
Duas pequenas Measure-Commandinvocações (100 vezes Get-Randomvs. random) me dizem que é cerca de 500 vezes mais lenta. Eu não sabia disso antes, para ser sincero. Mas é bom ter isso em mente, especialmente em loops com muitas iterações. Dito isto, o código golfed deve ser curto, não rápido ( que está sendo dito, é chato ter que esperar dois dias por uma resposta a um problema projeto Euler).
Joey
1
Meu problema era executar 10.000 iterações do cenário Monty Hall, cada uma exigindo três iterações de Get-Random. Um aumento de 50.000% no tempo de processamento, multiplicado por 30.000 execuções, é bastante desagradável.
Iszi
Uau. Parece que o mesmo provavelmente vale para qualquer apelido. Testado Get-Variablevs. gve obteve uma comparação semelhante.
Iszi
1
Pode ser isso. Fiz algumas contas e achei que meu script de Monty Hall levaria cerca de 1,5 horas (normalmente, 10 a 11 segundos) para ser executado sem Get-. É um inchaço bastante retorcido em tempo de execução, com uma economia de apenas 4 caracteres.
Iszi
8

for os loops podem ter algo entre 0 e três instruções no cabeçalho:

Loop infinito:

for(){}

Loop com inicialização:

for($n=0){}

Loop com inicialização e condição final:

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

Nesses casos, os pontos e vírgulas adicionais no final podem ser omitidos (é explicitamente declarado na especificação da linguagem , portanto não é um detalhe de implementação) em contraste com as linguagens do tipo C, que sempre exigem exatamente três instruções.

Isso também diminui whileum pouco. Comparar

while(...){}

e

for(;...){}

Com o bônus adicional que você pode colocar em uma linha anterior (se houver) na fortambém sem custo extra (e até mesmo salvar um personagem).

Joey
fonte
8

Se você estiver atribuindo uma matriz que você sabe que terá apenas dois valores, não use a indexação.

Algo assim:

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

Pode ser facilmente transformado em:

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

Isso também pode ser útil se você precisar apenas do primeiro elemento de uma matriz:

$a,$b=1..10
$a # 1
$b # 2..10
SomeShinyMonica
fonte
Neste caso (com as cordas) $a="apple";$o="orange"é idêntico em comprimento. São as matrizes mais longas que às vezes podem ser otimizadas bastante bem, por exemplo, colocando todos os elementos em uma string com um separador e depois usando -split(melhor usar espaços em branco como separador porque o unário -splitserá suficiente).
Joey
8

Transmitindo para string:

[string]$x

vs.

"$x"

A conversão para uma string como essa também pode ser usada para achatar uma matriz de strings, em vez de uni-la:

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

vs.

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

Converter uma sequência para um tipo numérico:

[int]$x     [float]$x

vs.

+$x

Também é muito útil saber que o PowerShell sempre usa o tipo do operando esquerdo para determinar o tipo final de uma expressão e as conversões a serem aplicadas:

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

o que pode ajudar a determinar onde estão os elencos desnecessários.

Joey
fonte
6

Não esqueça que nem sempre é necessário fornecer o nome completo de um parâmetro, e alguns parâmetros são posicionais.

Get-Random -InputObject (0..10)

... pode ser aparado para ...

Get-Random -I (0..10)

... porque "I", neste caso, é suficiente para identificar exclusivamente InputObjectos outros parâmetros válidos para este comando.

Você pode cortá-lo ainda mais para ...

Get-Random (0..10)

... porque InputObjecté um parâmetro posicional.

A tubulação geralmente é mais curta do que alimentar objetos como parâmetro, especialmente quando pode remover a necessidade de parênteses. Vamos cortar ainda mais nosso gerador de números aleatórios ...

0..10|Get-Random

Também esteja atento a outras maneiras de realizar a mesma coisa, mesmo que você não possa alterar o comando. Para o caso acima, você pode fazer o seguinte:

Get-Random 11

Ou, incorporando outra sugestão *:

Random 11

** Nota: A omissão Get-de um nome de comando pode aumentar o tempo de execução em cerca de 50.000%. Nada mal se você precisar do comando apenas uma vez, mas tenha cuidado ao usá-lo em loops longos. *

E é assim que se pode derrubar um simples comando em um terço do seu tamanho.

Iszi
fonte
6

Operador ternário falso. Você pode atribuir diretamente de uma ifinstrução:

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

Mas você pode usar uma matriz de 2 elementos e usar o teste para indexá-la. Os resultados $ falsey obtêm o elemento 0, os resultados $ truthy levam o elemento 1:

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

NB que isso realmente está indexando a matriz e, se o teste resultar em um valor que pode ser convertido em um número inteiro, você solicitará um item fora dos limites da matriz e receberá $ null de volta, e precisará fazer isso !(test)para forçar converter o resultado em um bool, com as opções invertidas.

TessellatingHeckler
fonte
O primeiro trecho não funcionou em um momento (versões mais antigas do PowerShell), se bem me lembro, tornando necessário envolvê-lo $(). Havia essencialmente uma distinção de usar pipelines feitos de comandos e instruções como expressões. Parece que está desaparecido até agora, pelo menos em PowerShell 5.
Joey
Além disso, se os elementos da matriz são não-estático, tanto ter analisado e processado como parte da criação matriz antes a indexação acontece eo resultado é atribuído. Por exemplo .
AdmBorkBork 25/05
6

Ao usar um número como argumento para um operador que, de outra forma, exigiria uma sequência, você pode usar o número diretamente. Comparar

...-join'0'

vs.

...-join0

Funciona com -splittambém. O argumento é sempre convertido em uma string primeiro.

Joey
fonte
Para referência, isso funciona -replacetambém.
AdmBorkBork
-replacetambém funciona com nenhum segundo argumento wheb que você deseja remover as correspondências;
Joey
5

Valor absoluto

Com

$n=-123

Ao invés de

[math]::abs($n)

usar

$n-replace'-'

Obviamente, as economias são canceladas se forem necessários parênteses.

Rynant
fonte
Ou se você precisa do resultado no lado esquerdo de um operador ;-)
Joey
5

Se você precisar silenciar erros, a variante óbvia seria

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

No entanto, isso é muito longo. Uma variante mais curta é executar o trybloco como um bloco de script e apenas redirecionar os erros para uma variável não definida ( $nullseria a usual, mas ainda é muito longa):

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

Isso economiza cinco bytes valiosos (se não o mundo).

Joey
fonte
5

Utilizar a $ofs variável especial para alterar a ó utput F ield S eparator utilizado quando stringifying uma matriz. Útil se você precisar transformar matrizes em seqüências de caracteres várias vezes.

Por exemplo:

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

Salva 2+ n caracteres no 2º -join, onde n é o comprimento do separador e salva 5+ n adicionais para o 3º -joine cada um deles posteriormente.

AdmBorkBork
fonte
1
Infelizmente, muito raramente é útil (pelo menos no meu golfe até agora - eu tendem a reduzi-lo a apenas uma única junção no final).
Joey
5

As variáveis ​​automáticas possuem booleanos para True e False como $truee, $falsemas você pode obter resultados semelhantes usando o operador lógico não !e os números inteiros 0 e 1 (ou qualquer número inteiro diferente de zero).

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Quase todas as expressões do PowerShell podem ser avaliadas como booleanas. Portanto, desde que você esteja ciente de como determinados dados são avaliados, é possível obter booleanos e nunca precisar convertê-los explicitamente. Esteja ciente do valor do LHS ao fazer isso.

  • O número inteiro 0 é falso e números inteiros diferentes de zero são avaliados como verdadeiros.
  • cadeias de comprimento diferentes de zero são verdadeiras e cadeias vazias ou nulas (e são nulas) são falsas.

Existem outros exemplos, mas você pode testar facilmente fazendo um elenco

PS C:\Users\matt> [bool]@(0)
False
Matt
fonte
1
Muitos outros tipos de dados também têm status semelhante. As variáveis ​​não inicializadas são padronizadas como $null, que é falsey. A cadeia vazia (e as variáveis ​​definidas para a cadeia vazia) são falsey. Etc. Isso pode ser usado para atalho a indexação em uma matriz (por exemplo, ao fazer um if/ else), como foi usado no FizzBuzz .
AdmBorkBork
@TimmyD Muito verdadeiro. Usando ints é apenas mais curto
Matt
@TimmyD eu queria responder fizzbuzz até que a sua serra .... Que não pode vencer .... pelo menos não ainda
Matt
Observe que, em muitos casos, você realmente não precisa de um bool. Você pode usar 0e 1também. Conversões implícitas ajudam muito nesse aspecto (que você pode frequentemente forçar com determinados operadores).
Joey
4

Invoke-Expressione Get-Randomtambém pode obter entrada de pipeline em vez de argumentos.

Para iexisso, permite salvar parênteses em algumas expressões:

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

Nesse caso, randompermite que um caso comum seja otimizado um pouco:

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

A última maneira de usá-lo simplesmente seleciona um item de uma lista. O -cargumento pode ser dado para permitir mais de uma única seleção.

Joey
fonte
4

Considere armazenar blocos de script repetidos em variáveis, em vez de usar funções.

Eu usaria isso para salvar alguns caracteres na minha implementação de Pedra, Papel e Tesoura antes de perceber que reescrever a função como uma variável tornava desnecessária a variável. No entanto, isso ainda pode ser útil para outros scripts, nos quais você está executando o mesmo código várias vezes.

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

vs.

$Hi={echo 'Hello, World!'};&$Hi
Iszi
fonte
2
Útil para funções que não aceitam argumentos. Caso contrário, isso params(...)ocuparia mais espaço do que a definição de função economiza. Relacionados: Use filtermais functionquando você pode fazê-lo.
Joey #
Você poderia usar $argspara evitar a necessidade de params; ie $x={$args[0]+2}(ou mesmo $x={2+"$args"}); pode salvar um personagem ou 2 em algumas circunstâncias. Você também pode combinar isso com outro truque para vários parâmetros:$x={$a,$b=$args;$a+$b+3}
JohnLBevan
4

Você pode usar $s|% t*yem vez [char[]]$sde dividir uma string para matriz de char. Dado pela resposta de TessellatingHeckler : % t*yexpande para | ForEach-Object -Method ToCharArrayequiv. do"$args".ToCharArray()

Por exemplo, compare

$s|% t*y

e

[char[]]$s

e

$s.ToCharArray()

É útil $argsprincipalmente:$args|% t*y

confuso
fonte
1
Isso é bem legal. Também usei o %truque para os membros algumas vezes, mas a maior parte do meu golfe é anterior a esse recurso ;-). Também é uma técnica geral: tente encontrar uma combinação de letra / curinga que corresponda à propriedade / método de que você precisa (e é mais curto que o real).
Joey
Outros exemplos úteis da resposta: $s|% *perpara $s.toUpper()e $s|% *werpara $s.toLower(). Eu concordo que é muito legal.
Mazzy
Mais um exemplo : |% t* "ddd\:hh\:mm\:ss"for[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy
Bem, isso é apenas um desperdício de citações; você não precisa deles aqui :-)
Joey
3

Use lógica booleana no lugar de contadores if em um loop

Suponha que você esteja adicionando todos os números pares de 1 a 10 ... 2+4+6+8+10=30

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

Você pode usar a negação booleana para reduzi-la para

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

para salvar um byte, mas que tal usar a conversão implícita de booleanos para ints e rolar a condicional para o acumulador

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

Salva 6 bytes neste exemplo.

AdmBorkBork
fonte
2
Jesus Cristo. Estou planejando fazer isso no meu código de produção no trabalho, meus colegas vão me amar por isso.
Chavez
3

Converter números de ponto flutuante em números inteiros no PowerShell é um campo minado. Por padrão, a conversão faz o arredondamento de banqueiros, que nem sempre diminui o número decimal e deixa o número inteiro menor, ou sempre arredonda 0,5 para o próximo número, como as pessoas fazem casualmente; seja surpreendente, por exemplo

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

e quebre os cálculos do codegolf. Muitos outros idiomas comuns fazem arredondamentos de truncamento; portanto, as perguntas sobre golfe geralmente exigem truncamento. Você pode procurar [Math]::Floor()a próxima melhor coisa, mas cuidado, isso só se comporta da mesma forma que o truncamento para números positivos, mas diminui os números negativos - mais longe do zero. [Math]::Truncate()é o que você precisa para alinhar o comportamento do PS ao arredondamento padrão de outro idioma, mas são muitos caracteres.

Regex substituindo dígitos após o ponto decimal pode ajudar a salvar alguns 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
fonte
3

Invertendo uma matriz

É útil em muitos desafios de , onde a saída é refletida de alguma maneira.

Suponha que você tenha

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

O método tradicional de reversão é longo, chato e não deixa a matriz no pipeline para uso imediato.

[array]::reverse($a)

A indexação direta na matriz na ordem inversa economiza alguns bytes, pois deixa os resultados no pipeline, mas ainda é bastante longa:

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

Em vez disso, tente um loop

$a|%{$a[-++$i]}
AdmBorkBork
fonte
a indexação inversa funciona bem quando há um limite superior para a contagem
Joey
3

A partir do PowerShell Core 6, você também pode usar intervalos para caracteres:

'a'..'z'

que pode substituir o muito mais pesado

0..25|%{[char]($_+97)}
Joey
fonte
Oh, isso será muito útil.
AdmBorkBork
1
[char[]](65..90)também é uma maneira útil de gerar o alfabeto
Veskah