Suggerimenti per giocare a golf in PowerShell


45

Quali suggerimenti generali hai per giocare a golf in Windows PowerShell? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale, almeno in qualche modo specifiche per PowerShell (ad esempio "rimuovere i commenti" non è una risposta). Si prega di inviare un suggerimento per risposta.

- preso quasi alla lettera dalla domanda di Marcog .


3
Quando ho cercato su Google "PowerShell golf" questo è stato il primo successo!
Matt

Risposte:


24

Poteri di 10 letterali con notazione scientifica:

4e6 = 4000000

Poteri di 2 letterali:

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

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

Potrebbe tornare utile.


19

Se è necessario eseguire un ciclo e si sa esattamente quante volte deve essere eseguito ogni volta, prendere in considerazione il piping di una matrice di numeri interi contigui ForEach-Objecttramite l' %alias invece di utilizzare for.

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

vs

1..10|%{...}


18

È possibile saltare spazi molto in PowerShell. Se sembra che potrebbe non essere necessario, molto probabilmente non lo è. Ciò è particolarmente utile nei confronti.

Esempio:

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

vs.

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

Se devi ramificare lo script in base al risultato di un singolo test che può avere più risultati, a switchvolte può abbinare o battere un'istruzione if.

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

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

vs.

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

Oppure (switch vs. if / elseif / else - switch vince per 15):

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

vs.

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

Se lo switch si basa effettivamente su determinati risultati matematici, come l'operazione modulo sopra, è possibile sostituirlo completamente con un array. Qui, salva altri 13 caratteri ed è persino più breve dell'istruzione if / else originale a due opzioni. (Grazie a Danko Durbic per questo pezzo.)

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

Se utilizzerai molto un determinato comando, in particolare uno senza un alias abbreviato preesistente, imposta un alias a carattere singolo all'inizio.

Esempio:

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

vs.

Get-Random 10;Get-Random 10;Get-Random 10

('even','odd')[$x%2]PER TUA INFORMAZIONE.
Incorrigible1

15

Incapsulare il comando che definisce una variabile tra parentesi consente di alimentare la definizione della variabile direttamente ad altri comandi.

Ad esempio, puoi impostare $ x e quindi impostare $ y in base al valore di $ x in un colpo solo con questo:

$y=($x=1)+1

Invece di questo:

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

È possibile impostare $ h e inviarlo con questo:

($h='Hello World!')

Invece di questo:

$h='Hello World!';$h

1
Ciò è particolarmente utile per chiamare metodi su oggetti. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
OrtografiaD

14

Un interruttore può agire come un ciclo, quando viene fornito un array. Per esempio:

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

Uscita:

FOO
BAR
MEH

Non sono del tutto sicuro di dove questo sarà utile, ma mi aspetto che sarà utile per qualcuno qualche volta.


2
È a portata di mano ogni volta che hai bisogno di una ForEach-Objecte switchall'interno di tale. È ad esempio un codice (nel mondo reale) molto utile per scrivere veloci parser di file di testo in cui è necessario fare cose diverse a seconda di quale regex corrisponde a una riga.
Joey,

Questo è ... dannatamente strano. Un array non dovrebbe corrispondere a un carattere, ma lo fa.
gatto

@Joey Ecco a cosa switch -File $pathserve
TheIncorrigible1

Non tutto ciò che viene analizzato sembra essere un file.
Joey,

12

Sostituisci [math]::powcon moltiplicazione. Invece di

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

tu puoi scrivere

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

Funziona con esponenti interi> = 0.


Avevo bisogno di vedere questa risposta per capire iex... Alias ​​perInvoke-Expression
HeatfanJohn

11

Gli operatori di confronto lavorano su raccolte di valori restituendo valori corrispondenti:

1..5 -gt 2

cederà 3, 4e 5. In alcuni casi questo può aiutare a risparmiare un tempo più lungo |?{$_...}.

-match è anche un operatore di confronto.


1
Nota che in questo esempio non hai bisogno di spazi1..5-gt2
Matt

1
Lo so; si trattava più di mostrare la tecnica. Gli spazi sono in una risposta separata .
Joey

11

Usa gli alias quando possibile. Ce ne sono molti utili:

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

11

Vuoi trovare il massimo o il minimo di una raccolta di valori? Provato

(...|measure -ma).Maximum

o

(...|measure -mi).Minimum

già?

Basta ordinare e utilizzare l'ultimo o il primo elemento:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum

1
E se conosci la lunghezza della raccolta di valori ed è inferiore a 10 ...
wizzwizz4,

@ wizzwizz4: Oh, le lunghezze massime possono spesso essere impiegate in modo creativo, non necessariamente in 10. Anche se in questo caso particolare non ricordo un caso in cui abbia mai aiutato.
Joey,

1
Voglio dire, se l'elemento finale è noto per essere 0, 1, 2, 3, 4, 5, 6, 7, 8o 9, si risparmierebbero un byte di scrivere la lunghezza nota al posto di -1.
wizzwizz4,

10

Accorciamento dei nomi delle proprietà

Purtroppo, diversamente dai parametri, le proprietà / i metodi (qualsiasi cosa a cui si accede con un punto .) non possono in genere essere abbreviati nella sua forma non ambigua.

Tuttavia, alcuni cmdlet possono operare su nomi di proprietà e accettare caratteri jolly e esistono insiemi di parametri poco noti di %e ?che possono essere utili.

Di solito passiamo in uno scriptblock e ci riferiamo all'elemento con $_, ma c'è un'altra forma di questi che prende un nome di proprietà e accetta un carattere jolly.

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

Con una proprietà come .Lengthquesta non possiamo usare la magia v3 che normalmente funzionerebbe su un array perché Lengthè una proprietà dell'array stesso, quindi i due precedenti potrebbero essere usati per ottenere le lunghezze dei singoli membri. La selectarriva in un po 'più breve.

Ma %può prendere direttamente un nome di proprietà e restituire quel valore:

$a|% Length

Che può essere abbreviato con caratteri jolly. Il carattere jolly deve essere risolto in una singola proprietà (o metodo, ne parleremo più avanti), quindi genererà un errore utile in caso contrario, indicando esattamente a quali membri potrebbe risolvere.

Nel caso di Length, Le*è in genere il più breve. Anche su una singola stringa, questo metodo è più corto di 1 byte rispetto all'uso della proprietà.

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

Ma a seconda di cosa stai facendo, questo può essere peggio. Puoi farlo $a.Length*5ma per farlo con l'espressione della pipeline dovresti avvolgerlo ($a|% Le*)*5; potrebbe comunque valerne la pena se è contro un array, ma il punto è che non è sempre appropriato come sostituzione diretta.

Funziona anche con i metodi e puoi tralasciare quello ()che rende un nome completo della stessa lunghezza, ma la stessa restrizione di cui sopra a volte a doverlo avvolgere. Il metodo deve avere un sovraccarico che non accetta parametri (è possibile passare argomenti posizionandoli dopo il nome del metodo, il che è davvero bello):

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

Con argomenti:

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

Questi non sono esattamente gli stessi in quanto l' -replaceoperatore esegue una sostituzione regex, ma se si sta semplicemente eseguendo una sostituzione di stringa, può (ora) essere più breve per utilizzare il metodo; aiuta che le stringhe siano argomenti del cmdlet anziché argomenti del metodo, quindi non è necessario che siano citate.

Proprietà Where-Object

?può anche prendere nomi di proprietà (parziali) e applicarvi un "operatore" (sotto forma di parametri switch). Anche in questo caso può essere più breve rispetto all'uso dell'approccio Where-Objectscriptblock standard se il nome della proprietà è sufficientemente lungo e univoco.

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

($a|% Le*)-gt5           # 14 - Lengths, not objs

1
Uno dei pochi posti in cui è richiesto spazio bianco. Bella scoperta, però. Posso pensare a diverse aree in cui questo accorcerà le cose.
AdmBorkBork,

Bella modifica Joey! Grazie.
Briantist,

Ti ho trovato un modo per renderlo più breve ;-) ... la cosa triste di questo è che nel suo insieme è di nuovo una pipeline, il che ne limita un po 'l'utilità. O meglio, ci sono molti posti in cui dovresti avvolgerlo di nuovo tra parentesi per ottenere un'espressione. Ma poche tecniche di golf sono senza compromessi ...
Joey,

1
@ConnorLSW ah sì, intendevo aggiornare questo dato che da allora avevo capito che puoi passare args in quel modo, il che aumenta notevolmente la sua utilità. Ottimo uso di .ToString()!
Briantist

2
@briantist ha trasformato PowerShell in un linguaggio molto più competitivo, eliminando davvero alcune delle chiamate .Net fastidiosamente dettagliate.
Colsw,

9

Trovare una somma a lungo termine:

(...|measure -s).Sum

Un modo più breve:

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

E ancora più breve:

...-join'+'|iex

9

I punti e virgola e le interruzioni di riga sono intercambiabili. Il codice golfizzato è spesso più leggibile se non bloccato in una singola riga. E la lunghezza è sempre la stessa (a condizione che tu usi U + 000A come interruzione di linea che PowerShell gestisce senza problemi).


2
Aspetta, siamo preoccupati per la leggibilità ?!
Kevin Cox,

4
Se non ha alcun effetto sulla lunghezza ... perché no?
Joey,

Tecnicamente non fa differenza dal momento che un punto e virgola ha un carattere in meno di \ r \ n? Solo in Unix è un singolare \ n.
Vasili Syrakis,

2
@Vasili: è possibile salvare correttamente i file con solo U + 000A tra le righe. PowerShell non si lamenterà. A proposito, ho già scritto nella risposta. Le interruzioni di riga sono una proprietà del file , non del sistema operativo su cui viene utilizzato. Nessuno afferma che non è possibile utilizzare i finali di linea Unix su Windows.
Joey,

@Joey Se hai usato una nuova installazione di Windows per fare una rapida programmazione, noterai che Notepad non funziona bene con \ x0a
Stan Strum

9

Il Getverbo è implicito. Questo può ridurre qualsiasi Get-Froba poco Frob. I contendenti frequenti sono dateo random.

Nota che questo non funzionerà correttamente in alcuni casi perché potresti avere utilità GNU nel tuo percorso (o altri programmi nativi che si scontrano). La ricerca dell'ordine dei comandi in quel caso sembra preferire il programma nativo prima di considerare i cmdlet con il Get-rimosso:

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

Questo non abbastanza sempre funziona come previsto. Ho una sceneggiatura che inizia con il nal g Get-Randomsalvataggio dei personaggi in seguito. Modificandolo in nal g Randommodo che lo script si blocchi indefinitamente (o, almeno, richieda una quantità eccessiva di tempo per l'elaborazione - non ho avuto la pazienza di aspettare che finisca, ma ci vogliono diversi ordini di grandezza più lunghi della forma originale prima di interrompere).
Iszi,

2
Due brevi Measure-Commandinvocazioni (100 volte Get-Randomcontro random) mi dicono che è circa 500 volte più lento. A dire il vero non lo sapevo prima. Ma è bene tenerlo a mente, specialmente in loop con molte iterazioni. Detto questo, il codice golfed deve essere breve, non veloce ( che viene detto, fa schifo dover aspettare due giorni per una risposta ad un problema Project Euler).
Joey,

1
Il mio problema era di eseguire 10.000 iterazioni dello scenario di Monty Hall, ognuna delle quali richiedeva tre iterazioni di Get-Random. Un aumento del 50.000% dei tempi di elaborazione, moltiplicato per 30.000 corse, è piuttosto sgradevole.
Iszi,

Wow. Sembra che lo stesso probabilmente valga per qualsiasi alias. Testato Get-Variablevs. gve ottenuto un confronto simile.
Iszi,

1
Potrebbe essere. Ho fatto un po 'di matematica e ho pensato che la mia sceneggiatura di Monty Hall avrebbe richiesto circa 1,5 ore (normalmente, 10-11 secondi) per funzionare senza Get-. È un gonfio piuttosto nodoso in fase di esecuzione per un risparmio di soli 4 caratteri di lunghezza.
Iszi,

8

for i loop possono avere qualcosa tra 0 e tre istruzioni nella loro intestazione:

Ciclo infinito:

for(){}

Loop con inizializzazione:

for($n=0){}

Ciclo con inizializzazione e condizione finale:

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

In questi casi i punti e virgola aggiuntivi alla fine possono essere omessi (è esplicitamente indicato nelle specifiche del linguaggio , quindi non è un dettaglio di implementazione) in contrasto con i linguaggi di tipo C che richiedono sempre esattamente tre istruzioni.

Questo rende anche whileun po 'più breve. Confrontare

while(...){}

e

for(;...){}

Con il bonus aggiunto che puoi inserire in una riga precedente (se ce n'è una) anche nel forcosto senza costi aggiuntivi (e persino salvando un personaggio).


8

Se stai assegnando un array che sai avrà solo due valori, non utilizzare l'indicizzazione.

Qualcosa come questo:

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

Può essere facilmente trasformato in questo:

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

Questo può essere utile anche se hai solo bisogno del primo elemento di un array:

$a,$b=1..10
$a # 1
$b # 2..10

In questo caso (con le stringhe) $a="apple";$o="orange"è identico in lunghezza. Sono le matrici più lunghe che a volte possono essere ottimizzate abbastanza bene, ad esempio mettendo tutti gli elementi in una stringa con un separatore e quindi usando -split(meglio usare gli spazi bianchi come separatore perché allora l'unario -splitsarà sufficiente).
Joey,

8

Casting su stringa:

[string]$x

vs.

"$x"

Il cast su una stringa come questa può anche essere usato per appiattire una matrice di stringhe, invece di unirla:

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

vs.

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

Trasmissione di una stringa a un tipo numerico:

[int]$x     [float]$x

vs.

+$x

Molto utile anche sapere che PowerShell prende sempre il tipo di operando di sinistra per determinare il tipo finale di un'espressione e le conversioni da applicare:

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

che può aiutare a determinare dove sono i cast inutili.


6

Non dimenticare che non è sempre necessario fornire il nome completo di un parametro e alcuni parametri sono posizionali.

Get-Random -InputObject (0..10)

... può essere tagliato in ...

Get-Random -I (0..10)

... perché "I", in questo caso, è sufficiente per identificarsi in modo univoco InputObjectdagli altri parametri validi per questo comando.

Potresti tagliarlo ulteriormente per ...

Get-Random (0..10)

... perché InputObjectè un parametro posizionale.

Le tubazioni sono generalmente più brevi rispetto all'alimentazione di oggetti come parametro, soprattutto quando possono rimuovere la necessità di parentesi. Tagliamo ulteriormente il nostro generatore di numeri casuali ...

0..10|Get-Random

Cerca anche altri modi per ottenere lo stesso risultato, anche se non puoi modificare il comando. Per il caso precedente, potresti fare questo:

Get-Random 11

Oppure, incorporando un altro suggerimento *:

Random 11

** Nota: l'omissione Get-dal nome di un comando può gonfiare il tempo di esecuzione di circa il 50.000%. Non male se hai solo bisogno del comando una volta, ma fai attenzione ad usarlo in cicli lunghi. *

Ed è così che può abbattere un semplice comando fino a un terzo della sua dimensione.


6

Operatore ternario falso. Puoi assegnare direttamente da ifun'istruzione:

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

Ma puoi usare un array a 2 elementi e usare il test per indicizzarlo. I risultati di $ falsey ottengono l'elemento 0, i risultati di $ truey prendono l'elemento 1:

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

NB. che questo sta realmente facendo l'indicizzazione dell'array, e se il test risulta in un valore che può essere lanciato su un numero intero, chiederai un oggetto al di fuori dei limiti dell'array e otterrai $ null indietro, e dovrai farlo !(test)per forzare getti il ​​risultato in un bool, con le opzioni invertite.


Il primo frammento non funzionava in un determinato momento (versioni precedenti di PowerShell), se ricordo bene, rendendo necessario avvolgerlo $(). C'era essenzialmente una distinzione nell'usare pipeline fatte da comandi e istruzioni come espressioni. Sembra che sia ormai passato, almeno in PowerShell 5.
Joey,

Inoltre, se gli elementi dell'array non sono statici, entrambi vengono analizzati ed elaborati come parte della creazione dell'array prima che avvenga l'indicizzazione e venga assegnato il risultato. Per esempio .
AdmBorkBork,

6

Quando si utilizza un numero come argomento per un operatore che altrimenti richiederebbe una stringa, è possibile utilizzare direttamente il numero. Confrontare

...-join'0'

vs.

...-join0

Funziona anche con -split. L'argomento viene sempre convertito prima in una stringa.


Per riferimento, funziona anche con questo -replace.
AdmBorkBork,

-replacefunziona anche senza nessun secondo argomento su cui desideri rimuovere le partite,
Joey,

5

Valore assoluto

Con

$n=-123

Invece di

[math]::abs($n)

uso

$n-replace'-'

Naturalmente, i risparmi vengono annullati se sono necessarie le parentesi.


O se hai bisogno del risultato sul lato sinistro di un operatore ;-)
Joey,

5

Se hai bisogno di mettere a tacere gli errori, la variante ovvia sarebbe

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

Tuttavia, questo è troppo lungo. Una variante più breve consiste trynell'eseguire il blocco come blocco di script e reindirizzare gli errori in una variabile non impostata ( $nullsarebbe la solita, ma è ancora troppo lunga):

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

Ciò consente di risparmiare cinque byte preziosi (se non il mondo).


5

Utilizzare la $ofs variabile speciale per modificare l' O scita F ield S eparator utilizzato quando stringifying un array. Utile se hai bisogno di trasformare più volte array in stringhe.

Per esempio:

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

Salva 2+ n caratteri nel 2 ° -join, dove n è la lunghezza del separatore e salva altri 5+ n per il 3 ° -joine ciascuno in seguito.


1
Purtroppo molto raramente utile (almeno nel mio golf finora - tendo a ridurlo a un solo join alla fine).
Joey

5

Le variabili automatiche hanno valori booleani di Vero e Falso come $truee $falsema è possibile ottenere risultati simili utilizzando l'operatore non logico !e gli interi 0 e 1 (o qualsiasi numero intero diverso da zero).

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Quasi tutte le espressioni di PowerShell possono essere valutate come booleane. Quindi, fintanto che sei consapevole di come vengono valutati determinati dati, puoi ottenere booleani e non devi mai lanciarli esplicitamente. Prestare attenzione al valore LHS durante queste operazioni.

  • Il numero intero 0 è falso e i numeri interi diversi da zero vengono valutati su vero.
  • le stringhe di lunghezza diversa da zero sono vere e vuote o le stringhe nulle (e gli stessi null) sono false.

Ci sono altri esempi ma puoi facilmente provare facendo un cast

PS C:\Users\matt> [bool]@(0)
False

1
Anche molti altri tipi di dati hanno uno stato simile. Le variabili non inizializzate sono predefinite su $null, che è false. La stringa vuota (e le variabili impostate sulla stringa vuota) sono false. Ecc. Questo può quindi essere usato per scorciare l'indicizzazione in un array (ad esempio, quando si fa un if/ else), come è stato usato in FizzBuzz .
AdmBorkBork

@TimmyD Molto vero. Usare ints è solo più breve
Matt

@TimmyD Volevo rispondere a fizzbuzz fino a quando non ho visto il tuo .... Non posso batterlo .... almeno non ancora
Matt

Si noti che in molti casi non è effettivamente necessario un bool. Puoi usare 0e 1anche. Le conversioni implicite aiutano molto in questo senso (che spesso puoi forzare con determinati operatori).
Joey

4

Invoke-Expressione Get-Randompuò anche ottenere input dalla pipeline anziché argomenti.

Per iexquesto consente di salvare le parentesi su alcune espressioni:

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

In questo caso randomconsente di ottimizzare un po 'un caso comune:

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

L'ultimo modo di usarlo seleziona semplicemente un elemento da un elenco. L' -cargomento può essere dato per consentire più di una singola selezione.


4

Prendi in considerazione l'archiviazione di blocchi di script ripetuti in variabili, anziché utilizzare le funzioni.

Stavo per usarlo per salvare alcuni personaggi nella mia implementazione Rock, Paper, Scissors prima di rendermi conto che riscrivere la funzione come variabile rendeva superflua anche la variabile. Questo potrebbe essere comunque utile per altri script, dove in realtà stai eseguendo lo stesso codice più volte.

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

vs.

$Hi={echo 'Hello, World!'};&$Hi

2
Utile per funzioni che non accettano argomenti. Altrimenti params(...)occuperebbe più spazio di quanto risparmi la definizione della funzione. Correlati: utilizzare filteroltre functionquando è possibile farlo.
Joey,

È possibile utilizzare $argsper evitare la necessità di params; cioè $x={$args[0]+2}(o anche $x={2+"$args"}); può salvare un personaggio o 2 in alcune circostanze. Puoi anche combinare questo con un altro trucco per più parametri:$x={$a,$b=$args;$a+$b+3}
JohnLBevan

4

È possibile utilizzare $s|% t*yinvece [char[]]$sper dividere una stringa in array di caratteri. Dato dalla risposta di TessellatingHeckler : si % t*yespande in | ForEach-Object -Method ToCharArrayequiv. di"$args".ToCharArray()

Ad esempio, confronta

$s|% t*y

e

[char[]]$s

e

$s.ToCharArray()

È utile $argssoprattutto:$args|% t*y


1
È abbastanza pulito. Ho usato il %trucco anche per i membri alcune volte, ma la maggior parte dei miei golf precede quella caratteristica ;-). È anche una tecnica abbastanza generale: prova a trovare una combinazione di lettere / caratteri jolly che corrisponda alla proprietà / metodo di cui hai bisogno (ed è più breve della cosa reale).
Joey,

Altri esempi utili dalla risposta: $s|% *perper $s.toUpper()e $s|% *werper $s.toLower(). Sono d'accordo che è abbastanza pulito.
mazzy

Un altro esempio : |% t* "ddd\:hh\:mm\:ss"per[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy, l'

Bene, allora è solo uno spreco di citazioni; non ne hai bisogno qui :-)
Joey


3

Usa la logica booleana al posto degli if-counter in un loop

Supponiamo di aggiungere tutti i numeri pari da 1 a 10 ... 2+4+6+8+10=30

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

È possibile utilizzare la negazione booleana per accorciarla

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

per salvare un byte, ma che ne dici invece di usare il cast implicito di booleani in ints e di arrotolare il condizionale nell'accumulatore

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

Salva 6 byte in questo esempio.


2
Gesù Cristo. Sto programmando di farlo nel mio codice di produzione al lavoro, i miei colleghi mi adoreranno per questo.
Chavez,

3

La conversione di numeri in virgola mobile in numeri interi in PowerShell è un po 'un campo minato. Per impostazione predefinita, la conversione fa l' arrotondamento dei banchieri, che non sempre taglia il decimale e lascia il numero intero più piccolo, o sempre arrotondato .5 fino al numero successivo come fanno le persone casualmente, arrotondando le pari in un modo e le probabilità in un altro - questo può essere sorprendente, ad es

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

e rompere i calcoli di codegolf. Molte altre lingue comuni eseguono arrotondamenti per troncamento, quindi le domande sul golf spesso richiedono troncamento. Potresti cercare [Math]::Floor()la prossima cosa migliore, ma attenzione, questo si comporta solo come il troncamento per i numeri positivi, ma prende i numeri negativi più in basso - più lontano da zero. [Math]::Truncate()è ciò di cui hai bisogno per allineare il comportamento di PS con l'arrotondamento predefinito di un'altra lingua, ma sono molti i personaggi.

Regex che sostituisce le cifre dopo il punto decimale può aiutare a salvare un paio di caratteri:

[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

3

Invertire una matrice

È utile in molte sfide di cui l'output si riflette in qualche modo.

Supponi di avere

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

Il metodo di inversione tradizionale è lungo, noioso e non lascia l'array sulla pipeline per un utilizzo immediato.

[array]::reverse($a)

L'indicizzazione diretta nell'array in ordine inverso consente di risparmiare alcuni byte, poiché lascia i risultati sulla pipeline, ma è ancora piuttosto lunga:

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

Invece, prova un loop

$a|%{$a[-++$i]}

l'indicizzazione inversa funziona bene quando c'è un limite superiore per il conteggio
Joey,

3

A partire da PowerShell Core 6, puoi anche usare intervalli per i personaggi:

'a'..'z'

che può sostituire il molto più ingombrante

0..25|%{[char]($_+97)}

Oh, questo tornerà utile.
AdmBorkBork,

1
[char[]](65..90)è anche un modo pratico per generare l'alfabeto
Veskah,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.